changeset 9115:79b098d44d20

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Mon, 15 Apr 2013 08:51:19 +0200
parents 01958088b87d (diff) 0298d8a0caf5 (current diff)
children e2dae636732a
files
diffstat 791 files changed, 27598 insertions(+), 15411 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Apr 04 11:57:04 2013 +0200
+++ b/.hgignore	Mon Apr 15 08:51:19 2013 +0200
@@ -4,6 +4,7 @@
 ^mx/ecj.jar
 ^mx/includes
 ^build/
+^build-nograal/
 ^dist/
 ^java/
 ^lib/
@@ -30,6 +31,7 @@
 \.dot$
 \.pyc$
 \.hprof$
+\javafilelist.txt$
 \.hprof\.txt$
 ^graal/.*/build.xml
 ^graal/.*/nbproject/
--- a/.hgtags	Thu Apr 04 11:57:04 2013 +0200
+++ b/.hgtags	Mon Apr 15 08:51:19 2013 +0200
@@ -320,3 +320,16 @@
 555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20
 6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79
 df5396524152118535c36da5801d828b560d19a2 hs25-b21
+4a198b201f3ce84433fa94a3ca65d061473e7c4c jdk8-b80
+dd6350b4abc4a6c19c89dd982cc0e4f3d119885c hs25-b22
+65b797426a3bec6e91b64085a0cfb94adadb634a jdk8-b81
+0631ebcc45f05c73b09a56c2586685af1f781c1d hs25-b23
+3db4ab0e12f437fe374817de346b2b0c6b4a5b31 jdk8-b82
+e3a41fc0234895eba4f272b984f7dacff495f8eb hs25-b24
+1c8db54ee9f315e20d6d5d9bf0b5c10349e9d301 jdk8-b83
+8d0f263a370c5f3e61791bb06054560804117288 hs25-b25
+af788b85010ebabbc1e8f52c6766e08c7a95cf99 jdk8-b84
+a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26
+42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85
+09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27
+6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/MacosxDebuggerLocal.m	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -40,12 +40,34 @@
 #import <errno.h>
 #import <sys/types.h>
 #import <sys/ptrace.h>
+#include "libproc_impl.h"
 
-jboolean debug = JNI_FALSE;
+#define UNSUPPORTED_ARCH "Unsupported architecture!"
+
+#if defined(x86_64) && !defined(amd64)
+#define amd64 1
+#endif
+
+#if amd64
+#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
+#else
+#error UNSUPPORTED_ARCH
+#endif
 
 static jfieldID symbolicatorID = 0; // set in _init0
 static jfieldID taskID = 0; // set in _init0
 
+static jfieldID p_ps_prochandle_ID = 0;
+static jfieldID loadObjectList_ID = 0;
+static jmethodID listAdd_ID = 0;
+
+static jmethodID createClosestSymbol_ID = 0;
+static jmethodID createLoadObject_ID = 0;
+static jmethodID getJavaThreadsInfo_ID = 0;
+
+// indicator if thread id (lwpid_t) was set
+static bool _threads_filled = false;
+
 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) {
   (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator);
 }
@@ -76,6 +98,11 @@
   (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
 }
 
+static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
+  jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
+  return (struct ps_prochandle*)(intptr_t)ptr;
+}
+
 #if defined(__i386__)
     #define hsdb_thread_state_t     x86_thread_state32_t
     #define hsdb_float_state_t      x86_float_state32_t
@@ -91,7 +118,7 @@
     #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
     #define HSDB_FLOAT_STATE_COUNT  x86_FLOAT_STATE64_COUNT
 #else
-    #error "Unsupported architecture"
+    #error UNSUPPORTED_ARCH
 #endif
 
 /*
@@ -104,6 +131,66 @@
   symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
   taskID = (*env)->GetFieldID(env, cls, "task", "J");
   CHECK_EXCEPTION;
+
+  // for core file
+  p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
+  CHECK_EXCEPTION;
+  loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
+  CHECK_EXCEPTION;
+
+  // methods we use
+  createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
+                    "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
+  CHECK_EXCEPTION;
+  createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
+                    "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
+  CHECK_EXCEPTION;
+
+  // java.util.List method we call
+  jclass listClass = (*env)->FindClass(env, "java/util/List");
+  CHECK_EXCEPTION;
+  listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
+  CHECK_EXCEPTION;
+  getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo",
+                                                     "()[J");
+  CHECK_EXCEPTION;
+
+  init_libproc(getenv("LIBSAPROC_DEBUG") != NULL);
+}
+
+JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
+  (JNIEnv *env, jclass cls)
+{
+#ifdef _LP64
+  return 8;
+#else
+  #error UNSUPPORTED_ARCH
+#endif
+}
+
+/** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */
+jlong lookupByNameIncore(
+  JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName)
+{
+  const char *objectName_cstr, *symbolName_cstr;
+  jlong addr;
+  jboolean isCopy;
+  objectName_cstr = NULL;
+  if (objectName != NULL) {
+    objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
+    CHECK_EXCEPTION_(0);
+  }
+  symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
+  CHECK_EXCEPTION_(0);
+
+  print_debug("look for %s \n", symbolName_cstr);
+  addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
+
+  if (objectName_cstr != NULL) {
+    (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
+  }
+  (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
+  return addr;
 }
 
 /*
@@ -116,14 +203,17 @@
   JNIEnv *env, jobject this_obj, 
   jstring objectName, jstring symbolName) 
 {
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  if (ph->core != NULL) {
+    return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
+  }
+
   jlong address = 0;
 
 JNF_COCOA_ENTER(env);
   NSString *symbolNameString = JNFJavaToNSString(env, symbolName);
 
-  if (debug) {
-    printf("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
-  }
+  print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
 
   id symbolicator = getSymbolicator(env, this_obj);
   if (symbolicator != nil) {
@@ -131,9 +221,7 @@
     address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
   }
 
-  if (debug) {
-    printf("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
-  }
+  print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
 JNF_COCOA_EXIT(env);
 
   return address;
@@ -141,6 +229,42 @@
 
 /*
  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method:    lookupByAddress0
+ * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
+ */
+JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
+  (JNIEnv *env, jobject this_obj, jlong addr) {
+  uintptr_t offset;
+  const char* sym = NULL;
+
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
+  if (sym == NULL) return 0;
+  return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
+                          (*env)->NewStringUTF(env, sym), (jlong)offset);
+}
+
+/** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */
+jbyteArray readBytesFromCore(
+  JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes)
+{
+  jboolean isCopy;
+  jbyteArray array;
+  jbyte *bufPtr;
+  ps_err_e err;
+
+  array = (*env)->NewByteArray(env, numBytes);
+  CHECK_EXCEPTION_(0);
+  bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
+  CHECK_EXCEPTION_(0);
+
+  err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
+  (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
+  return (err == PS_OK)? array : 0;
+}
+
+/*
+ * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
  * Method:    readBytesFromProcess0
  * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
  */
@@ -149,18 +273,21 @@
   JNIEnv *env, jobject this_obj, 
   jlong addr, jlong numBytes) 
 {
-  if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
+  print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
 
   // must allocate storage instead of using former parameter buf
-  jboolean isCopy;
   jbyteArray array;
-  jbyte *bufPtr;
+
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  if (ph->core != NULL) {
+    return readBytesFromCore(env, ph, this_obj, addr, numBytes);
+  }
 
   array = (*env)->NewByteArray(env, numBytes);
   CHECK_EXCEPTION_(0);
 
   unsigned long alignedAddress;
-  unsigned long alignedLength;
+  unsigned long alignedLength = 0;
   kern_return_t result;
   vm_offset_t *pages;
   int *mapped;
@@ -189,7 +316,7 @@
     // assume all failures are unmapped pages
   }
 
-  if (debug) fprintf(stderr, "%ld pages\n", pageCount);
+  print_debug("%ld pages\n", pageCount);
 	
   remaining = numBytes;
 	
@@ -207,7 +334,7 @@
     }
 
     if (mapped[i]) {
-      if (debug) fprintf(stderr, "page %d mapped (len %ld start %ld)\n", i, len, start);
+      print_debug("page %d mapped (len %ld start %ld)\n", i, len, start);
       (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start));
       vm_deallocate(mach_task_self(), pages[i], vm_page_size);
     }
@@ -220,6 +347,115 @@
   return array;
 }
 
+/** Only used for core file reading, set thread_id for threads which is got after core file parsed.
+  * Thread context is available in Mach-O core file but thread id is not. We can get thread id
+  * from Threads which store all java threads information when they are created. Here we can identify
+  * them as java threads by checking if a thread's rsp or rbp within a java thread's stack.
+  * Note Macosx uses unique_thread_id which is different from other platforms though printed ids
+  * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long
+  * integers to host all java threads' id, stack_start, stack_end as:
+  * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...]
+  *
+  * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet). 
+  * This function should be called only once if succeeded
+  */ 
+bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
+  int n = 0, i = 0, j;
+  struct reg regs;
+  
+  jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID);
+  CHECK_EXCEPTION_(false);
+  int len = (int)(*env)->GetArrayLength(env, thrinfos);
+  uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL);
+  CHECK_EXCEPTION_(false); 
+  n = get_num_threads(ph);
+  print_debug("fill_java_threads called, num_of_thread = %d\n", n);
+  for (i = 0; i < n; i++) {
+    if (!get_nth_lwp_regs(ph, i, &regs)) {
+      print_debug("Could not get regs of thread %d, already set!\n", i);
+      return false;
+    }
+    for (j = 0; j < len; j += 3) {
+      lwpid_t  uid = cinfos[j];
+      uint64_t beg = cinfos[j + 1];
+      uint64_t end = cinfos[j + 2]; 
+      if ((regs.r_rsp < end && regs.r_rsp >= beg) ||
+          (regs.r_rbp < end && regs.r_rbp >= beg)) {
+        set_lwp_id(ph, i, uid);
+        break;
+      }
+    }
+  }
+  (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
+  CHECK_EXCEPTION_(false);
+  return true;
+}
+
+/* For core file only, called from
+ * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
+ */
+jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id) {
+  if (!_threads_filled)  {
+    if (!fill_java_threads(env, this_obj, get_proc_handle(env, this_obj))) {
+      throw_new_debugger_exception(env, "Failed to fill in threads");
+      return 0;
+    } else {
+      _threads_filled = true;
+    }
+  }
+
+  struct reg gregs;
+  jboolean isCopy;
+  jlongArray array;
+  jlong *regs;
+
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
+    THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
+  }
+
+#undef NPRGREG
+#undef REG_INDEX
+#if amd64
+#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
+
+  array = (*env)->NewLongArray(env, NPRGREG);
+  CHECK_EXCEPTION_(0);
+  regs = (*env)->GetLongArrayElements(env, array, &isCopy);
+
+  regs[REG_INDEX(R15)] = gregs.r_r15;
+  regs[REG_INDEX(R14)] = gregs.r_r14;
+  regs[REG_INDEX(R13)] = gregs.r_r13;
+  regs[REG_INDEX(R12)] = gregs.r_r12;
+  regs[REG_INDEX(RBP)] = gregs.r_rbp;
+  regs[REG_INDEX(RBX)] = gregs.r_rbx;
+  regs[REG_INDEX(R11)] = gregs.r_r11;
+  regs[REG_INDEX(R10)] = gregs.r_r10;
+  regs[REG_INDEX(R9)]  = gregs.r_r9;
+  regs[REG_INDEX(R8)]  = gregs.r_r8;
+  regs[REG_INDEX(RAX)] = gregs.r_rax;
+  regs[REG_INDEX(RCX)] = gregs.r_rcx;
+  regs[REG_INDEX(RDX)] = gregs.r_rdx;
+  regs[REG_INDEX(RSI)] = gregs.r_rsi;
+  regs[REG_INDEX(RDI)] = gregs.r_rdi;
+  regs[REG_INDEX(RIP)] = gregs.r_rip;
+  regs[REG_INDEX(CS)]  = gregs.r_cs;
+  regs[REG_INDEX(RSP)] = gregs.r_rsp;
+  regs[REG_INDEX(SS)]  = gregs.r_ss;
+  regs[REG_INDEX(FSBASE)] = 0;
+  regs[REG_INDEX(GSBASE)] = 0;
+  regs[REG_INDEX(DS)] = gregs.r_ds;
+  regs[REG_INDEX(ES)] = gregs.r_es;
+  regs[REG_INDEX(FS)] = gregs.r_fs;
+  regs[REG_INDEX(GS)] = gregs.r_gs;
+  regs[REG_INDEX(TRAPNO)] = gregs.r_trapno;
+  regs[REG_INDEX(RFL)]    = gregs.r_rflags;
+
+#endif /* amd64 */
+  (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
+  return array;
+}
 
 /*
  * Lookup the thread_t that corresponds to the given thread_id.
@@ -232,9 +468,7 @@
  */
 thread_t
 lookupThreadFromThreadId(task_t task, jlong thread_id) {
-  if (debug) {
-    printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
-  }
+  print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
   
   thread_array_t thread_list = NULL;
   mach_msg_type_number_t thread_list_count = 0;
@@ -244,9 +478,7 @@
   // 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);
-    }
+    print_debug("task_threads returned 0x%x\n", result);
     return 0;
   }
   
@@ -257,9 +489,7 @@
     // 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);
-      }
+      print_debug("thread_info returned 0x%x\n", result);
       break;
     }
     
@@ -288,15 +518,17 @@
   JNIEnv *env, jobject this_obj, 
   jlong thread_id) 
 {
-  if (debug)
-    printf("getThreadRegisterSet0 called\n");
+  print_debug("getThreadRegisterSet0 called\n");
+
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  if (ph->core != NULL) {
+    return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id);
+  }
 
   kern_return_t result;
   thread_t tid;
   mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT;
   hsdb_thread_state_t state;
-  unsigned int *r;
-  int i;
   jlongArray registerArray;
   jlong *primitiveArray;
   task_t gTask = getTask(env, this_obj);
@@ -306,97 +538,56 @@
   result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
 
   if (result != KERN_SUCCESS) {
-    if (debug)
-      printf("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
+    print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
     return NULL;
   }
 
-  // 40 32-bit registers on ppc, 16 on x86. 
-  // Output order is the same as the order in the ppc_thread_state/i386_thread_state struct.
-#if defined(__i386__)
-	r = (unsigned int *)&state;
-	registerArray = (*env)->NewLongArray(env, 8);
-	primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
-	primitiveArray[0] = r[0];  // eax
-	primitiveArray[1] = r[2];  // ecx
-	primitiveArray[2] = r[3];  // edx
-	primitiveArray[3] = r[1];  // ebx
-	primitiveArray[4] = r[7];  // esp
-	primitiveArray[5] = r[6];  // ebp
-	primitiveArray[6] = r[5];  // esi
-	primitiveArray[7] = r[4];  // edi
-	(*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
-#elif defined(__x86_64__)
-	/* From AMD64ThreadContext.java
-	   public static final int R15 = 0;
-	   public static final int R14 = 1;
-	   public static final int R13 = 2;
-	   public static final int R12 = 3;
-	   public static final int R11 = 4;
-	   public static final int R10 = 5;
-	   public static final int R9  = 6;
-	   public static final int R8  = 7;
-	   public static final int RDI = 8;
-	   public static final int RSI = 9;
-	   public static final int RBP = 10;
-	   public static final int RBX = 11;
-	   public static final int RDX = 12;
-	   public static final int RCX = 13;
-	   public static final int RAX = 14;
-	   public static final int TRAPNO = 15;
-	   public static final int ERR = 16;
-	   public static final int RIP = 17;
-	   public static final int CS = 18;
-	   public static final int RFL = 19;
-	   public static final int RSP = 20;
-	   public static final int SS = 21;
-	   public static final int FS = 22;
-	   public static final int GS = 23;
-	   public static final int ES = 24;
-	   public static final int DS = 25;
-	   public static final int FSBASE = 26;
-	   public static final int GSBASE = 27;
-	 */
-	// 64 bit
-	if (debug) printf("Getting threads for a 64-bit process\n");
-	registerArray = (*env)->NewLongArray(env, 28);
-	primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
+#if amd64
+#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
+#undef REG_INDEX
+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
+
+  // 64 bit
+  print_debug("Getting threads for a 64-bit process\n");
+  registerArray = (*env)->NewLongArray(env, NPRGREG);
+  CHECK_EXCEPTION_(0);
+  primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
 
-	primitiveArray[0] = state.__r15;
-	primitiveArray[1] = state.__r14;
-	primitiveArray[2] = state.__r13;
-	primitiveArray[3] = state.__r12;
-	primitiveArray[4] = state.__r11;
-	primitiveArray[5] = state.__r10;
-	primitiveArray[6] = state.__r9;
-	primitiveArray[7] = state.__r8;
-	primitiveArray[8] = state.__rdi;
-	primitiveArray[9] = state.__rsi;
-	primitiveArray[10] = state.__rbp;
-	primitiveArray[11] = state.__rbx;
-	primitiveArray[12] = state.__rdx;
-	primitiveArray[13] = state.__rcx;
-	primitiveArray[14] = state.__rax;
-	primitiveArray[15] = 0;             // trapno ?
-	primitiveArray[16] = 0;             // err ?
-	primitiveArray[17] = state.__rip;
-	primitiveArray[18] = state.__cs;
-	primitiveArray[19] = state.__rflags;
-	primitiveArray[20] = state.__rsp;
-	primitiveArray[21] = 0;            // We don't have SS
-	primitiveArray[22] = state.__fs;
-	primitiveArray[23] = state.__gs;
-	primitiveArray[24] = 0;
-	primitiveArray[25] = 0;
-	primitiveArray[26] = 0;
-	primitiveArray[27] = 0;
+  primitiveArray[REG_INDEX(R15)] = state.__r15;
+  primitiveArray[REG_INDEX(R14)] = state.__r14;
+  primitiveArray[REG_INDEX(R13)] = state.__r13;
+  primitiveArray[REG_INDEX(R12)] = state.__r12;
+  primitiveArray[REG_INDEX(R11)] = state.__r11;
+  primitiveArray[REG_INDEX(R10)] = state.__r10;
+  primitiveArray[REG_INDEX(R9)]  = state.__r9;
+  primitiveArray[REG_INDEX(R8)]  = state.__r8;
+  primitiveArray[REG_INDEX(RDI)] = state.__rdi;
+  primitiveArray[REG_INDEX(RSI)] = state.__rsi;
+  primitiveArray[REG_INDEX(RBP)] = state.__rbp;
+  primitiveArray[REG_INDEX(RBX)] = state.__rbx;
+  primitiveArray[REG_INDEX(RDX)] = state.__rdx;
+  primitiveArray[REG_INDEX(RCX)] = state.__rcx;
+  primitiveArray[REG_INDEX(RAX)] = state.__rax;
+  primitiveArray[REG_INDEX(TRAPNO)] = 0;            // trapno, not used
+  primitiveArray[REG_INDEX(ERR)]    = 0;            // err, not used 
+  primitiveArray[REG_INDEX(RIP)] = state.__rip;
+  primitiveArray[REG_INDEX(CS)]  = state.__cs;
+  primitiveArray[REG_INDEX(RFL)] = state.__rflags;
+  primitiveArray[REG_INDEX(RSP)] = state.__rsp;
+  primitiveArray[REG_INDEX(SS)] = 0;                // We don't have SS
+  primitiveArray[REG_INDEX(FS)] = state.__fs;
+  primitiveArray[REG_INDEX(GS)] = state.__gs;
+  primitiveArray[REG_INDEX(ES)] = 0;
+  primitiveArray[REG_INDEX(DS)] = 0;
+  primitiveArray[REG_INDEX(FSBASE)] = 0;
+  primitiveArray[REG_INDEX(GSBASE)] = 0;
+  print_debug("set registers\n");
 
-	if (debug) printf("set registers\n");
+  (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
 
-	(*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
 #else
-#error Unsupported architecture
-#endif
+#error UNSUPPORTED_ARCH
+#endif /* amd64 */
 
   return registerArray;
 }
@@ -410,8 +601,7 @@
 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);
+  print_debug("translateTID0 called on tid = 0x%x\n", (int)tid);
 
   kern_return_t result;
   thread_t foreign_tid, usable_tid;
@@ -426,8 +616,7 @@
   if (result != KERN_SUCCESS)
     return -1;
     
-  if (debug)
-    printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
+  print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
     
   return (jint) usable_tid;
 }
@@ -437,7 +626,7 @@
   // 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);
+    print_error("attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
     return false;
   }
   return true;
@@ -461,11 +650,11 @@
           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));
+          print_error("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);
+        print_error("attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
         return false;
       }
     } else {
@@ -474,13 +663,13 @@
           continue;
           break;
         case ECHILD:
-          fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          print_error("attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
           break;
         case EINVAL:
-          fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n");
+          print_error("attach: waitpid() failed. Invalid options argument.\n");
           break;
         default:
-          fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno);
+          print_error("attach: waitpid() failed. Unexpected error %d\n",errno);
           break;
       }
       return false;
@@ -492,7 +681,7 @@
 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);
+    print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
     return false;
   } else {
     return ptrace_waitpid(pid);
@@ -504,23 +693,19 @@
  * Method:    attach0
  * Signature: (I)V
  */
-JNIEXPORT void JNICALL 
+JNIEXPORT void JNICALL
 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
-  JNIEnv *env, jobject this_obj, jint jpid) 
+  JNIEnv *env, jobject this_obj, jint jpid)
 {
+  print_debug("attach0 called for jpid=%d\n", (int)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);
   if (result != KERN_SUCCESS) {
-    fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result);
+    print_error("attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result);
     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
   }
   putTask(env, this_obj, gTask);
@@ -550,18 +735,79 @@
 JNF_COCOA_EXIT(env);
 }
 
+/** For core file, 
+    called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
+static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
+  int n = 0, i = 0;
+
+  // add load objects
+  n = get_num_libs(ph);
+  for (i = 0; i < n; i++) {
+     uintptr_t base;
+     const char* name;
+     jobject loadObject;
+     jobject loadObjectList;
+
+     base = get_lib_base(ph, i);
+     name = get_lib_name(ph, i);
+     loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
+                                   (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
+     CHECK_EXCEPTION;
+     loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
+     CHECK_EXCEPTION;
+     (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
+     CHECK_EXCEPTION;
+  }
+}
+
+/*
+ * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method:    attach0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(
+  JNIEnv *env, jobject this_obj, jstring execName, jstring coreName)
+{
+  const char *execName_cstr;
+  const char *coreName_cstr;
+  jboolean isCopy;
+  struct ps_prochandle* ph;
+
+  execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
+  CHECK_EXCEPTION;
+  coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
+  CHECK_EXCEPTION;
+
+  print_debug("attach: %s %s\n", execName_cstr, coreName_cstr);
+
+  if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
+    (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
+    (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
+    THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
+  }
+  (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
+  (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
+  (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
+  fillLoadObjects(env, this_obj, ph);
+}
+
 /*
  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
  * Method:    detach0
  * Signature: ()V
  */
-JNIEXPORT void JNICALL 
+JNIEXPORT void JNICALL
 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
-  JNIEnv *env, jobject this_obj) 
+  JNIEnv *env, jobject this_obj)
 {
+  print_debug("detach0 called\n");
+  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+  if (ph != NULL && ph->core != NULL) {
+     Prelease(ph);
+     return;
+  }
 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
@@ -569,15 +815,15 @@
   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);
+    print_error("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);
+      print_error("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) {
@@ -585,170 +831,3 @@
   }
 JNF_COCOA_EXIT(env);
 }
-
-/*
- * Class:     sun_jvm_hotspot_asm_Disassembler
- * 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) 
-{
-  uintptr_t func = 0;
-  const char* error_message = NULL;
-  const char* java_home;
-  jboolean isCopy;
-  uintptr_t *handle = NULL;
-
-  const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
-  const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
-  char buffer[128];
-
-  /* Load the hsdis library */
-  void* hsdis_handle;
-  hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
-  if (hsdis_handle == NULL) {
-    snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
-    hsdis_handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL);
-  }
-  if (hsdis_handle != NULL) {
-    func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual");
-  }
-  if (func == 0) {
-    error_message = dlerror();
-    fprintf(stderr, "%s\n", error_message);
-  }
-
-  (*env)->ReleaseStringUTFChars(env, libname_s, libname);
-  (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
-
-  if (func == 0) {
-    /* Couldn't find entry point.  error_message should contain some
-     * platform dependent error message.
-     */
-    THROW_NEW_DEBUGGER_EXCEPTION(error_message);
-  }
-  return (jlong)func;
-}
-
-/* signature of decode_instructions_virtual from hsdis.h */
-typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
-                             unsigned char* start, uintptr_t length,
-                             void* (*event_callback)(void*, const char*, void*),
-                             void* event_stream,
-                             int (*printf_callback)(void*, const char*, ...),
-                             void* printf_stream,
-                             const char* options);
-
-/* container for call back state when decoding instructions */
-typedef struct {
-  JNIEnv* env;
-  jobject dis;
-  jobject visitor;
-  jmethodID handle_event;
-  jmethodID raw_print;
-  char buffer[4096];
-} decode_env;
-
-
-/* event callback binding to Disassembler.handleEvent */
-static void* event_to_env(void* env_pv, const char* event, void* arg) {
-  decode_env* denv = (decode_env*)env_pv;
-  JNIEnv* env = denv->env;
-  jstring event_string = (*env)->NewStringUTF(env, event);
-  jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
-                                        event_string, (jlong) (uintptr_t)arg);
-  /* ignore exceptions for now */
-  CHECK_EXCEPTION_CLEAR_((void *)0);
-  return (void*)(uintptr_t)result;
-}
-
-/* printing callback binding to Disassembler.rawPrint */
-static int printf_to_env(void* env_pv, const char* format, ...) {
-  jstring output;
-  va_list ap;
-  int cnt;
-  decode_env* denv = (decode_env*)env_pv;
-  JNIEnv* env = denv->env;
-  size_t flen = strlen(format);
-  const char* raw = NULL;
-
-  if (flen == 0)  return 0;
-  if (flen < 2 ||
-      strchr(format, '%') == NULL) {
-    raw = format;
-  } else if (format[0] == '%' && format[1] == '%' &&
-             strchr(format+2, '%') == NULL) {
-    // happens a lot on machines with names like %foo
-    flen--;
-    raw = format+1;
-  }
-  if (raw != NULL) {
-    jstring output = (*env)->NewStringUTF(env, raw);
-    (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
-    CHECK_EXCEPTION_CLEAR;
-    return (int) flen;
-  }
-  va_start(ap, format);
-  cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap);
-  va_end(ap);
-
-  output = (*env)->NewStringUTF(env, denv->buffer);
-  (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
-  CHECK_EXCEPTION_CLEAR;
-  return cnt;
-}
-
-/*
- * Class:     sun_jvm_hotspot_asm_Disassembler
- * 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) 
-{
-  jboolean isCopy;
-  jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
-  jbyte* end = start + (*env)->GetArrayLength(env, code);
-  const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy);
-  jclass disclass = (*env)->GetObjectClass(env, dis);
-
-  decode_env denv;
-  denv.env = env;
-  denv.dis = dis;
-  denv.visitor = visitor;
-
-  /* find Disassembler.handleEvent callback */
-  denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
-                                          "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
-  CHECK_EXCEPTION_CLEAR_VOID
-
-  /* find Disassembler.rawPrint callback */
-  denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
-                                       "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
-  CHECK_EXCEPTION_CLEAR_VOID
-
-  /* decode the buffer */
-  (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
-                                                         startPc + end - start,
-                                                         (unsigned char*)start,
-                                                         end - start,
-                                                         &event_to_env,  (void*) &denv,
-                                                         &printf_to_env, (void*) &denv,
-                                                         options);
-
-  /* cleanup */
-  (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
-  (*env)->ReleaseStringUTFChars(env, options_s, options);
-}
--- a/agent/src/os/bsd/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/Makefile	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2009, 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
@@ -22,34 +22,60 @@
 #  
 #
 
-ARCH := $(shell if ([ `uname -m` = "ia64" ])  ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
+ARCH := $(shell if ([ `uname -m` = "ia64" ])  ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "x86_64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
+
+OS       := $(shell uname -s)
+
 GCC      = gcc
 
 JAVAH    = ${JAVA_HOME}/bin/javah
 
+ifneq ($(OS), Darwin)
 SOURCES  = salibelf.c   \
         symtab.c        \
 	libproc_impl.c  \
 	ps_proc.c       \
 	ps_core.c       \
 	BsdDebuggerLocal.c
-
-INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
-
-OBJS     = $(SOURCES:.c=.o)
+OBJS    = $(SOURCES:.c=.o)
+OBJSPLUS = $(OBJS) sadis.o
+LIBSA = $(ARCH)/libsaproc.so
 
 LIBS     = -lutil -lthread_db
 
-CFLAGS   = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES)
+else
 
-LIBSA = $(ARCH)/libsaproc.so
+SOURCES  = symtab.c     \
+	libproc_impl.c  \
+	ps_core.c
+OBJS    = $(SOURCES:.c=.o)
+OBJSPLUS = MacosxDebuggerLocal.o sadis.o $(OBJS)
+EXTINCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers -I.
+EXTCFLAGS = -m64 -D__APPLE__ -framework JavaNativeFoundation
+FOUNDATIONFLAGS = -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
+LIBSA = $(ARCH)/libsaproc.dylib
+endif   # Darwin
+
+INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") $(EXTINCLUDE)
+
+
+
+CFLAGS   = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) $(EXTCFLAGS)
+
+
 
 all: $(LIBSA)
 
-BsdDebuggerLocal.o: BsdDebuggerLocal.c
-	$(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses  \
+MacosxDebuggerLocal.o: MacosxDebuggerLocal.m
+	echo "OS="$(OS)
+	$(JAVAH) -jni -classpath ../../../build/classes  \
 		sun.jvm.hotspot.debugger.x86.X86ThreadContext \
 		sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
+	$(GCC) $(CFLAGS) $(FOUNDATIONFLAGS) $<
+
+sadis.o: ../../share/native/sadis.c
+	$(JAVAH) -jni -classpath ../../../build/classes \
+		sun.jvm.hotspot.asm.Disassembler
 	$(GCC) $(CFLAGS) $<
 
 .c.obj:
@@ -59,9 +85,9 @@
   LFLAGS_LIBSA = -Xlinker --version-script=mapfile
 endif
 
-$(LIBSA): $(OBJS) mapfile
+$(LIBSA): $(OBJSPLUS) mapfile 
 	if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi
-	$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS)
+	$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(FOUNDATIONFLAGS) $(OBJSPLUS) $(LIBS) $(SALIBS)
 
 test.o: $(LIBSA) test.c
 	$(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c
@@ -71,7 +97,6 @@
 
 clean:
 	rm -f $(LIBSA)
-	rm -f $(OBJS)
+	rm -f *.o
 	rm -f test.o
 	-rmdir $(ARCH)
-
--- a/agent/src/os/bsd/libproc.h	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/libproc.h	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, 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,9 +27,38 @@
 
 #include <unistd.h>
 #include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef __APPLE__
+typedef enum ps_err_e {
+  PS_OK, PS_ERR, PS_BADPID, PS_BADLID,
+  PS_BADADDR, PS_NOSYM, PS_NOFREGS
+} ps_err_e;
+
+#ifndef psaddr_t
+#define psaddr_t uintptr_t
+#endif
+
+#ifndef bool
+typedef int bool;
+#define true  1
+#define false 0
+#endif  // bool
+
+#ifndef lwpid_t
+#define lwpid_t uintptr_t
+#endif
+
+#include <mach/thread_status.h>
+#else   // __APPLE__
+#include <elf.h>
+#include <link.h>
 #include <machine/reg.h>
 #include <proc_service.h>
-
 #if defined(sparc) || defined(sparcv9)
 /*
   If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
@@ -44,6 +73,14 @@
 
 #endif //sparc or sparcv9
 
+// This C bool type must be int for compatibility with BSD calls and
+// it would be a mistake to equivalence it to C++ bool on many platforms
+typedef int bool;
+#define true  1
+#define false 0
+
+#endif // __APPLE__
+
 /************************************************************************************
 
 0. This is very minimal subset of Solaris libproc just enough for current application.
@@ -72,13 +109,7 @@
 
 *************************************************************************************/
 
-// This C bool type must be int for compatibility with BSD calls and
-// it would be a mistake to equivalence it to C++ bool on many platforms
-
-typedef int bool;
-#define true  1
-#define false 0
-
+struct reg;
 struct ps_prochandle;
 
 // attach to a process
--- a/agent/src/os/bsd/libproc_impl.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/libproc_impl.c	Mon Apr 15 08:51:19 2013 +0200
@@ -21,12 +21,6 @@
  * questions.
  *
  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <thread_db.h>
 #include "libproc_impl.h"
 
 static const char* alt_root = NULL;
@@ -34,61 +28,65 @@
 
 #define SA_ALTROOT "SA_ALTROOT"
 
+off_t ltell(int fd) {
+  return lseek(fd, 0, SEEK_CUR);
+}
+
 static void init_alt_root() {
-   if (alt_root_len == -1) {
-      alt_root = getenv(SA_ALTROOT);
-      if (alt_root) {
-         alt_root_len = strlen(alt_root);
-      } else {
-         alt_root_len = 0;
-      }
-   }
+  if (alt_root_len == -1) {
+    alt_root = getenv(SA_ALTROOT);
+    if (alt_root) {
+      alt_root_len = strlen(alt_root);
+    } else {
+      alt_root_len = 0;
+    }
+  }
 }
 
 int pathmap_open(const char* name) {
-   int fd;
-   char alt_path[PATH_MAX + 1];
+  int fd;
+  char alt_path[PATH_MAX + 1];
+
+  init_alt_root();
 
-   init_alt_root();
-   fd = open(name, O_RDONLY);
-   if (fd >= 0) {
+  if (alt_root_len > 0) {
+    strcpy(alt_path, alt_root);
+    strcat(alt_path, name);
+    fd = open(alt_path, O_RDONLY);
+    if (fd >= 0) {
+      print_debug("path %s substituted for %s\n", alt_path, name);
       return fd;
-   }
+    }
 
-   if (alt_root_len > 0) {
+    if (strrchr(name, '/')) {
       strcpy(alt_path, alt_root);
-      strcat(alt_path, name);
+      strcat(alt_path, strrchr(name, '/'));
       fd = open(alt_path, O_RDONLY);
       if (fd >= 0) {
-         print_debug("path %s substituted for %s\n", alt_path, name);
-         return fd;
+        print_debug("path %s substituted for %s\n", alt_path, name);
+        return fd;
       }
-
-      if (strrchr(name, '/')) {
-         strcpy(alt_path, alt_root);
-         strcat(alt_path, strrchr(name, '/'));
-         fd = open(alt_path, O_RDONLY);
-         if (fd >= 0) {
-            print_debug("path %s substituted for %s\n", alt_path, name);
-            return fd;
-         }
-      }
-   }
-
-   return -1;
+    }
+  } else {
+    fd = open(name, O_RDONLY);
+    if (fd >= 0) {
+      return fd;
+    }
+  }
+  return -1;
 }
 
 static bool _libsaproc_debug;
 
 void print_debug(const char* format,...) {
-   if (_libsaproc_debug) {
-     va_list alist;
+  if (_libsaproc_debug) {
+    va_list alist;
 
-     va_start(alist, format);
-     fputs("libsaproc DEBUG: ", stderr);
-     vfprintf(stderr, format, alist);
-     va_end(alist);
-   }
+    va_start(alist, format);
+    fputs("libsaproc DEBUG: ", stderr);
+    vfprintf(stderr, format, alist);
+    va_end(alist);
+  }
 }
 
 void print_error(const char* format,...) {
@@ -100,172 +98,235 @@
 }
 
 bool is_debug() {
-   return _libsaproc_debug;
+  return _libsaproc_debug;
 }
 
+#ifdef __APPLE__
+// get arch offset in file
+bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) {
+  struct fat_header fatheader;
+  struct fat_arch fatarch;
+  off_t img_start = 0;
+
+  off_t pos = ltell(fd);
+  if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) {
+    return false;
+  }
+  if (fatheader.magic == FAT_CIGAM) {
+    int i;
+    for (i = 0; i < ntohl(fatheader.nfat_arch); i++) {
+      if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) {
+        return false;
+      }
+      if (ntohl(fatarch.cputype) == cputype) {
+        print_debug("fat offset=%x\n", ntohl(fatarch.offset));
+        img_start = ntohl(fatarch.offset);
+        break;
+      }
+    }
+    if (img_start == 0) {
+      return false;
+    }
+  }
+  lseek(fd, pos, SEEK_SET);
+  *offset = img_start;
+  return true;
+}
+
+bool is_macho_file(int fd) {
+  mach_header_64 fhdr;
+  off_t x86_64_off;
+
+  if (fd < 0) {
+    print_debug("Invalid file handle passed to is_macho_file\n");
+    return false;
+  }
+
+  off_t pos = ltell(fd);
+  // check fat header
+  if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) {
+    print_debug("failed to get fat header\n");
+    return false;
+  }
+  lseek(fd, x86_64_off, SEEK_SET);
+  if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
+     return false;
+  }
+  lseek(fd, pos, SEEK_SET);               // restore
+  print_debug("fhdr.magic %x\n", fhdr.magic);
+  return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64);
+}
+
+#endif //__APPLE__
+
 // initialize libproc
 bool init_libproc(bool debug) {
-   // init debug mode
    _libsaproc_debug = debug;
-
+#ifndef __APPLE__
    // initialize the thread_db library
    if (td_init() != TD_OK) {
      print_debug("libthread_db's td_init failed\n");
      return false;
    }
-
+#endif // __APPLE__
    return true;
 }
 
-static void destroy_lib_info(struct ps_prochandle* ph) {
-   lib_info* lib = ph->libs;
-   while (lib) {
-     lib_info *next = lib->next;
-     if (lib->symtab) {
-        destroy_symtab(lib->symtab);
-     }
-     free(lib);
-     lib = next;
-   }
+void destroy_lib_info(struct ps_prochandle* ph) {
+  lib_info* lib = ph->libs;
+  while (lib) {
+    lib_info* next = lib->next;
+    if (lib->symtab) {
+      destroy_symtab(lib->symtab);
+    }
+    free(lib);
+    lib = next;
+  }
 }
 
-static void destroy_thread_info(struct ps_prochandle* ph) {
-   thread_info* thr = ph->threads;
-   while (thr) {
-     thread_info *next = thr->next;
-     free(thr);
-     thr = next;
-   }
+void destroy_thread_info(struct ps_prochandle* ph) {
+  sa_thread_info* thr = ph->threads;
+  while (thr) {
+    sa_thread_info* n = thr->next;
+    free(thr);
+    thr = n;
+  }
 }
 
 // ps_prochandle cleanup
-
-// ps_prochandle cleanup
 void Prelease(struct ps_prochandle* ph) {
-   // do the "derived class" clean-up first
-   ph->ops->release(ph);
-   destroy_lib_info(ph);
-   destroy_thread_info(ph);
-   free(ph);
+  // do the "derived class" clean-up first
+  ph->ops->release(ph);
+  destroy_lib_info(ph);
+  destroy_thread_info(ph);
+  free(ph);
 }
 
 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
-   return add_lib_info_fd(ph, libname, -1, base);
+  return add_lib_info_fd(ph, libname, -1, base);
 }
 
 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
    lib_info* newlib;
+  print_debug("add_lib_info_fd %s\n", libname);
 
-   if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
-      print_debug("can't allocate memory for lib_info\n");
-      return NULL;
-   }
-
-   strncpy(newlib->name, libname, sizeof(newlib->name));
-   newlib->base = base;
+  if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
+    print_debug("can't allocate memory for lib_info\n");
+    return NULL;
+  }
 
-   if (fd == -1) {
-      if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
-         print_debug("can't open shared object %s\n", newlib->name);
-         free(newlib);
-         return NULL;
-      }
-   } else {
-      newlib->fd = fd;
-   }
+  strncpy(newlib->name, libname, sizeof(newlib->name));
+  newlib->base = base;
 
-   // check whether we have got an ELF file. /proc/<pid>/map
-   // gives out all file mappings and not just shared objects
-   if (is_elf_file(newlib->fd) == false) {
-      close(newlib->fd);
+  if (fd == -1) {
+    if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
+      print_debug("can't open shared object %s\n", newlib->name);
       free(newlib);
       return NULL;
-   }
-
-   newlib->symtab = build_symtab(newlib->fd);
-   if (newlib->symtab == NULL) {
-      print_debug("symbol table build failed for %s\n", newlib->name);
-   }
-   else {
-      print_debug("built symbol table for %s\n", newlib->name);
-   }
+    }
+  } else {
+    newlib->fd = fd;
+  }
 
-   // even if symbol table building fails, we add the lib_info.
-   // This is because we may need to read from the ELF file for core file
-   // address read functionality. lookup_symbol checks for NULL symtab.
-   if (ph->libs) {
-      ph->lib_tail->next = newlib;
-      ph->lib_tail = newlib;
-   }  else {
-      ph->libs = ph->lib_tail = newlib;
-   }
-   ph->num_libs++;
+#ifdef __APPLE__
+  // check whether we have got an Macho file.
+  if (is_macho_file(newlib->fd) == false) {
+    close(newlib->fd);
+    free(newlib);
+    print_debug("not a mach-o file\n");
+    return NULL;
+  }
+#else
+  // check whether we have got an ELF file. /proc/<pid>/map
+  // gives out all file mappings and not just shared objects
+  if (is_elf_file(newlib->fd) == false) {
+    close(newlib->fd);
+    free(newlib);
+    return NULL;
+  }
+#endif // __APPLE__
 
-   return newlib;
+  newlib->symtab = build_symtab(newlib->fd);
+  if (newlib->symtab == NULL) {
+    print_debug("symbol table build failed for %s\n", newlib->name);
+  } else {
+    print_debug("built symbol table for %s\n", newlib->name);
+  }
+
+  // even if symbol table building fails, we add the lib_info.
+  // This is because we may need to read from the ELF file or MachO file for core file
+  // address read functionality. lookup_symbol checks for NULL symtab.
+  if (ph->libs) {
+    ph->lib_tail->next = newlib;
+    ph->lib_tail = newlib;
+  }  else {
+    ph->libs = ph->lib_tail = newlib;
+  }
+  ph->num_libs++;
+  return newlib;
 }
 
 // lookup for a specific symbol
 uintptr_t lookup_symbol(struct ps_prochandle* ph,  const char* object_name,
                        const char* sym_name) {
-   // ignore object_name. search in all libraries
-   // FIXME: what should we do with object_name?? The library names are obtained
-   // by parsing /proc/<pid>/maps, which may not be the same as object_name.
-   // What we need is a utility to map object_name to real file name, something
-   // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
-   // now, we just ignore object_name and do a global search for the symbol.
+  // ignore object_name. search in all libraries
+  // FIXME: what should we do with object_name?? The library names are obtained
+  // by parsing /proc/<pid>/maps, which may not be the same as object_name.
+  // What we need is a utility to map object_name to real file name, something
+  // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
+  // now, we just ignore object_name and do a global search for the symbol.
 
-   lib_info* lib = ph->libs;
-   while (lib) {
-      if (lib->symtab) {
-         uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
-         if (res) return res;
-      }
-      lib = lib->next;
-   }
+  lib_info* lib = ph->libs;
+  while (lib) {
+    if (lib->symtab) {
+      uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
+      if (res) return res;
+    }
+    lib = lib->next;
+  }
 
-   print_debug("lookup failed for symbol '%s' in obj '%s'\n",
+  print_debug("lookup failed for symbol '%s' in obj '%s'\n",
                           sym_name, object_name);
-   return (uintptr_t) NULL;
+  return (uintptr_t) NULL;
 }
 
-
 const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
-   const char* res = NULL;
-   lib_info* lib = ph->libs;
-   while (lib) {
-      if (lib->symtab && addr >= lib->base) {
-         res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
-         if (res) return res;
-      }
-      lib = lib->next;
-   }
-   return NULL;
+  const char* res = NULL;
+  lib_info* lib = ph->libs;
+  while (lib) {
+    if (lib->symtab && addr >= lib->base) {
+      res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
+      if (res) return res;
+    }
+    lib = lib->next;
+  }
+  return NULL;
 }
 
 // add a thread to ps_prochandle
-thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
-   thread_info* newthr;
-   if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
-      print_debug("can't allocate memory for thread_info\n");
-      return NULL;
-   }
+sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
+  sa_thread_info* newthr;
+  if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) {
+    print_debug("can't allocate memory for thread_info\n");
+    return NULL;
+  }
 
-   // initialize thread info
-   newthr->pthread_id = pthread_id;
-   newthr->lwp_id = lwp_id;
+  // initialize thread info
+  newthr->pthread_id = pthread_id;
+  newthr->lwp_id = lwp_id;
 
-   // add new thread to the list
-   newthr->next = ph->threads;
-   ph->threads = newthr;
-   ph->num_threads++;
-   return newthr;
+  // add new thread to the list
+  newthr->next = ph->threads;
+  ph->threads = newthr;
+  ph->num_threads++;
+  return newthr;
 }
 
-
+#ifndef __APPLE__
 // struct used for client data from thread_db callback
 struct thread_db_client_data {
-   struct ps_prochandle* ph;
-   thread_info_callback callback;
+  struct ps_prochandle* ph;
+  thread_info_callback callback;
 };
 
 // callback function for libthread_db
@@ -314,6 +375,7 @@
   return true;
 }
 
+#endif // __APPLE__
 
 // get number of threads
 int get_num_threads(struct ps_prochandle* ph) {
@@ -322,18 +384,54 @@
 
 // get lwp_id of n'th thread
 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
-   int count = 0;
-   thread_info* thr = ph->threads;
-   while (thr) {
-      if (count == index) {
-         return thr->lwp_id;
-      }
-      count++;
-      thr = thr->next;
-   }
-   return -1;
+  int count = 0;
+  sa_thread_info* thr = ph->threads;
+  while (thr) {
+    if (count == index) {
+      return thr->lwp_id;
+    }
+    count++;
+    thr = thr->next;
+  }
+  return 0;
 }
 
+#ifdef __APPLE__
+// set lwp_id of n'th thread
+bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) {
+  int count = 0;
+  sa_thread_info* thr = ph->threads;
+  while (thr) {
+    if (count == index) {
+      thr->lwp_id = lwpid;
+      return true;
+    }
+    count++;
+    thr = thr->next;
+  }
+  return false;
+}
+
+// get regs of n-th thread, only used in fillThreads the first time called
+bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) {
+  int count = 0;
+  sa_thread_info* thr = ph->threads;
+  while (thr) {
+    if (count == index) {
+      break;
+    }
+    count++;
+    thr = thr->next;
+  }
+  if (thr != NULL) {
+    memcpy(regs, &thr->regs, sizeof(struct reg));
+    return true;
+  }
+  return false;
+}
+
+#endif // __APPLE__
+
 // get regs for a given lwp
 bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
   return ph->ops->get_lwp_regs(ph, lwp_id, regs);
@@ -341,35 +439,35 @@
 
 // get number of shared objects
 int get_num_libs(struct ps_prochandle* ph) {
-   return ph->num_libs;
+  return ph->num_libs;
 }
 
 // get name of n'th solib
 const char* get_lib_name(struct ps_prochandle* ph, int index) {
-   int count = 0;
-   lib_info* lib = ph->libs;
-   while (lib) {
-      if (count == index) {
-         return lib->name;
-      }
-      count++;
-      lib = lib->next;
-   }
-   return NULL;
+  int count = 0;
+  lib_info* lib = ph->libs;
+  while (lib) {
+    if (count == index) {
+      return lib->name;
+    }
+    count++;
+    lib = lib->next;
+  }
+  return NULL;
 }
 
 // get base address of a lib
 uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
-   int count = 0;
-   lib_info* lib = ph->libs;
-   while (lib) {
-      if (count == index) {
-         return lib->base;
-      }
-      count++;
-      lib = lib->next;
-   }
-   return (uintptr_t)NULL;
+  int count = 0;
+  lib_info* lib = ph->libs;
+  while (lib) {
+    if (count == index) {
+      return lib->base;
+    }
+    count++;
+    lib = lib->next;
+  }
+  return (uintptr_t)NULL;
 }
 
 bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
@@ -425,6 +523,7 @@
   va_end(alist);
 }
 
+#ifndef __APPLE__
 // ------------------------------------------------------------------------
 // Functions below this point are not yet implemented. They are here only
 // to make the linker happy.
@@ -458,3 +557,4 @@
   print_debug("ps_pcontinue not implemented\n");
   return PS_OK;
 }
+#endif // __APPLE__
--- a/agent/src/os/bsd/libproc_impl.h	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/libproc_impl.h	Mon Apr 15 08:51:19 2013 +0200
@@ -30,6 +30,60 @@
 #include "libproc.h"
 #include "symtab.h"
 
+#ifdef __APPLE__
+#include <inttypes.h>     // for PRIx64, 32, ...
+#include <pthread.h>
+#include <mach-o/loader.h>
+#include <mach-o/nlist.h>
+#include <mach-o/fat.h>
+
+#ifndef register_t
+#define register_t uint64_t
+#endif
+
+/*** registers copied from bsd/amd64 */
+typedef struct reg {
+  register_t      r_r15;
+  register_t      r_r14;
+  register_t      r_r13;
+  register_t      r_r12;
+  register_t      r_r11;
+  register_t      r_r10;
+  register_t      r_r9;
+  register_t      r_r8;
+  register_t      r_rdi;
+  register_t      r_rsi;
+  register_t      r_rbp;
+  register_t      r_rbx;
+  register_t      r_rdx;
+  register_t      r_rcx;
+  register_t      r_rax;
+  uint32_t        r_trapno;      // not used
+  uint16_t        r_fs;
+  uint16_t        r_gs;
+  uint32_t        r_err;         // not used
+  uint16_t        r_es;          // not used
+  uint16_t        r_ds;          // not used
+  register_t      r_rip;
+  register_t      r_cs;
+  register_t      r_rflags;
+  register_t      r_rsp;
+  register_t      r_ss;          // not used
+} reg;
+
+// convenient defs
+typedef struct mach_header_64 mach_header_64;
+typedef struct load_command load_command;
+typedef struct segment_command_64 segment_command_64;
+typedef struct thread_command thread_command;
+typedef struct dylib_command dylib_command;
+typedef struct symtab_command symtab_command;
+typedef struct nlist_64 nlist_64;
+#else
+#include <thread_db.h>
+#include "salibelf.h"
+#endif //  __APPLE__
+
 // data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h
 
 #define BUF_SIZE     (PATH_MAX + NAME_MAX + 1)
@@ -44,12 +98,12 @@
 } lib_info;
 
 // list of threads
-typedef struct thread_info {
-   lwpid_t                  lwp_id;
-   pthread_t                pthread_id; // not used cores, always -1
+typedef struct sa_thread_info {
+   lwpid_t                  lwp_id;     // same as pthread_t
+   pthread_t                pthread_id; //
    struct reg               regs;       // not for process, core uses for caching regset
-   struct thread_info*      next;
-} thread_info;
+   struct sa_thread_info*   next;
+} sa_thread_info;
 
 // list of virtual memory maps
 typedef struct map_info {
@@ -91,6 +145,7 @@
    // part of the class sharing workaround
    map_info*          class_share_maps;// class share maps in a linked list
    map_info**         map_array; // sorted (by vaddr) array of map_info pointers
+   char               exec_path[4096];  // file name java
 };
 
 struct ps_prochandle {
@@ -100,12 +155,11 @@
    lib_info*          libs;      // head of lib list
    lib_info*          lib_tail;  // tail of lib list - to append at the end
    int                num_threads;
-   thread_info*       threads;   // head of thread list
+   sa_thread_info*    threads;   // head of thread list
    struct core_data*  core;      // data only used for core dumps, NULL for process
 };
 
 int pathmap_open(const char* name);
-
 void print_debug(const char* format,...);
 void print_error(const char* format,...);
 bool is_debug();
@@ -122,10 +176,45 @@
 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
                           uintptr_t base);
 
-// adds a new thread to threads list, returns NULL on failure
-thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
-
+sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
 // a test for ELF signature without using libelf
+
+#ifdef __APPLE__
+// a test for Mach-O signature
+bool is_macho_file(int fd);
+// skip fat head to get image start offset of cpu_type_t
+// return false if any error happens, else value in offset.
+bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset);
+#else
 bool is_elf_file(int fd);
+#endif // __APPLE__
+
+lwpid_t get_lwp_id(struct ps_prochandle* ph, int index);
+bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid);
+bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs);
+
+// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
+// of the load object object_name in the target process identified by ph.
+// It returns the symbol's value as an address in the target process in
+// *sym_addr.
 
+ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
+                    const char *sym_name, psaddr_t *sym_addr);
+
+// read "size" bytes info "buf" from address "addr"
+ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t  addr,
+                  void *buf, size_t size);
+
+// write "size" bytes of data to debuggee at address "addr"
+ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
+                   const void *buf, size_t size);
+
+// fill in ptrace_lwpinfo for lid
+ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo);
+
+// needed for when libthread_db is compiled with TD_DEBUG defined
+void ps_plog (const char *format, ...);
+
+// untility, tells the position in file
+off_t ltell(int fd);
 #endif //_LIBPROC_IMPL_H_
--- a/agent/src/os/bsd/ps_core.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/ps_core.c	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -28,10 +28,11 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include <elf.h>
-#include <link.h>
 #include "libproc_impl.h"
-#include "salibelf.h"
+
+#ifdef __APPLE__
+#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
+#endif
 
 // This file has the libproc implementation to read core files.
 // For live processes, refer to ps_proc.c. Portions of this is adapted
@@ -41,156 +42,158 @@
 // ps_prochandle cleanup helper functions
 
 // close all file descriptors
-static void close_elf_files(struct ps_prochandle* ph) {
-   lib_info* lib = NULL;
+static void close_files(struct ps_prochandle* ph) {
+  lib_info* lib = NULL;
+  // close core file descriptor
+  if (ph->core->core_fd >= 0)
+    close(ph->core->core_fd);
 
-   // close core file descriptor
-   if (ph->core->core_fd >= 0)
-     close(ph->core->core_fd);
+  // close exec file descriptor
+  if (ph->core->exec_fd >= 0)
+    close(ph->core->exec_fd);
 
-   // close exec file descriptor
-   if (ph->core->exec_fd >= 0)
-     close(ph->core->exec_fd);
+  // close interp file descriptor
+  if (ph->core->interp_fd >= 0)
+    close(ph->core->interp_fd);
 
-   // close interp file descriptor
-   if (ph->core->interp_fd >= 0)
-     close(ph->core->interp_fd);
-
-   // close class share archive file
-   if (ph->core->classes_jsa_fd >= 0)
-     close(ph->core->classes_jsa_fd);
+  // close class share archive file
+  if (ph->core->classes_jsa_fd >= 0)
+    close(ph->core->classes_jsa_fd);
 
-   // close all library file descriptors
-   lib = ph->libs;
-   while (lib) {
-      int fd = lib->fd;
-      if (fd >= 0 && fd != ph->core->exec_fd) close(fd);
-      lib = lib->next;
-   }
+  // close all library file descriptors
+  lib = ph->libs;
+  while (lib) {
+    int fd = lib->fd;
+    if (fd >= 0 && fd != ph->core->exec_fd) {
+      close(fd);
+    }
+    lib = lib->next;
+  }
 }
 
 // clean all map_info stuff
 static void destroy_map_info(struct ps_prochandle* ph) {
   map_info* map = ph->core->maps;
   while (map) {
-     map_info* next = map->next;
-     free(map);
-     map = next;
+    map_info* next = map->next;
+    free(map);
+    map = next;
   }
 
   if (ph->core->map_array) {
-     free(ph->core->map_array);
+    free(ph->core->map_array);
   }
 
   // Part of the class sharing workaround
   map = ph->core->class_share_maps;
   while (map) {
-     map_info* next = map->next;
-     free(map);
-     map = next;
+    map_info* next = map->next;
+    free(map);
+    map = next;
   }
 }
 
 // ps_prochandle operations
 static void core_release(struct ps_prochandle* ph) {
-   if (ph->core) {
-      close_elf_files(ph);
-      destroy_map_info(ph);
-      free(ph->core);
-   }
+  if (ph->core) {
+    close_files(ph);
+    destroy_map_info(ph);
+    free(ph->core);
+  }
 }
 
 static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) {
-   map_info* map;
-   if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
-      print_debug("can't allocate memory for map_info\n");
-      return NULL;
-   }
+  map_info* map;
+  if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
+    print_debug("can't allocate memory for map_info\n");
+    return NULL;
+  }
 
-   // initialize map
-   map->fd     = fd;
-   map->offset = offset;
-   map->vaddr  = vaddr;
-   map->memsz  = memsz;
-   return map;
+  // initialize map
+  map->fd     = fd;
+  map->offset = offset;
+  map->vaddr  = vaddr;
+  map->memsz  = memsz;
+  return map;
 }
 
 // add map info with given fd, offset, vaddr and memsz
 static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
                              uintptr_t vaddr, size_t memsz) {
-   map_info* map;
-   if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
-      return NULL;
-   }
+  map_info* map;
+  if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
+    return NULL;
+  }
 
-   // add this to map list
-   map->next  = ph->core->maps;
-   ph->core->maps   = map;
-   ph->core->num_maps++;
+  // add this to map list
+  map->next  = ph->core->maps;
+  ph->core->maps   = map;
+  ph->core->num_maps++;
 
-   return map;
+  return map;
 }
 
 // Part of the class sharing workaround
 static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
                              uintptr_t vaddr, size_t memsz) {
-   map_info* map;
-   if ((map = allocate_init_map(ph->core->classes_jsa_fd,
-                                offset, vaddr, memsz)) == NULL) {
-      return NULL;
-   }
+  map_info* map;
+  if ((map = allocate_init_map(ph->core->classes_jsa_fd,
+                               offset, vaddr, memsz)) == NULL) {
+    return NULL;
+  }
 
-   map->next = ph->core->class_share_maps;
-   ph->core->class_share_maps = map;
-   return map;
+  map->next = ph->core->class_share_maps;
+  ph->core->class_share_maps = map;
+  return map;
 }
 
 // Return the map_info for the given virtual address.  We keep a sorted
 // array of pointers in ph->map_array, so we can binary search.
 static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
 {
-   int mid, lo = 0, hi = ph->core->num_maps - 1;
-   map_info *mp;
+  int mid, lo = 0, hi = ph->core->num_maps - 1;
+  map_info *mp;
 
-   while (hi - lo > 1) {
-     mid = (lo + hi) / 2;
-      if (addr >= ph->core->map_array[mid]->vaddr)
-         lo = mid;
-      else
-         hi = mid;
-   }
+  while (hi - lo > 1) {
+    mid = (lo + hi) / 2;
+    if (addr >= ph->core->map_array[mid]->vaddr) {
+      lo = mid;
+    } else {
+      hi = mid;
+    }
+  }
 
-   if (addr < ph->core->map_array[hi]->vaddr)
-      mp = ph->core->map_array[lo];
-   else
-      mp = ph->core->map_array[hi];
+  if (addr < ph->core->map_array[hi]->vaddr) {
+    mp = ph->core->map_array[lo];
+  } else {
+    mp = ph->core->map_array[hi];
+  }
 
-   if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz)
-      return (mp);
+  if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
+    return (mp);
+  }
 
 
-   // Part of the class sharing workaround
-   // Unfortunately, we have no way of detecting -Xshare state.
-   // Check out the share maps atlast, if we don't find anywhere.
-   // This is done this way so to avoid reading share pages
-   // ahead of other normal maps. For eg. with -Xshare:off we don't
-   // want to prefer class sharing data to data from core.
-   mp = ph->core->class_share_maps;
-   if (mp) {
-      print_debug("can't locate map_info at 0x%lx, trying class share maps\n",
-             addr);
-   }
-   while (mp) {
-      if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
-         print_debug("located map_info at 0x%lx from class share maps\n",
-                  addr);
-         return (mp);
-      }
-      mp = mp->next;
-   }
+  // Part of the class sharing workaround
+  // Unfortunately, we have no way of detecting -Xshare state.
+  // Check out the share maps atlast, if we don't find anywhere.
+  // This is done this way so to avoid reading share pages
+  // ahead of other normal maps. For eg. with -Xshare:off we don't
+  // want to prefer class sharing data to data from core.
+  mp = ph->core->class_share_maps;
+  if (mp) {
+    print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr);
+  }
+  while (mp) {
+    if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
+      print_debug("located map_info at 0x%lx from class share maps\n", addr);
+      return (mp);
+    }
+    mp = mp->next;
+  }
 
-   print_debug("can't locate map_info at 0x%lx\n", addr);
-   return (NULL);
+  print_debug("can't locate map_info at 0x%lx\n", addr);
+  return (NULL);
 }
 
 //---------------------------------------------------------------
@@ -239,157 +242,171 @@
 };
 
 static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
-   jboolean i;
-   if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
-      *pvalue = i;
-      return true;
-   } else {
-      return false;
-   }
+  jboolean i;
+  if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
+    *pvalue = i;
+    return true;
+  } else {
+    return false;
+  }
 }
 
 static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
-   uintptr_t uip;
-   if (ps_pread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) {
-      *pvalue = uip;
-      return true;
-   } else {
-      return false;
-   }
+  uintptr_t uip;
+  if (ps_pread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) {
+    *pvalue = uip;
+    return true;
+  } else {
+    return false;
+  }
 }
 
 // used to read strings from debuggee
 static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) {
-   size_t i = 0;
-   char  c = ' ';
+  size_t i = 0;
+  char  c = ' ';
 
-   while (c != '\0') {
-     if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK)
-         return false;
-      if (i < size - 1)
-         buf[i] = c;
-      else // smaller buffer
-         return false;
-      i++; addr++;
-   }
-
-   buf[i] = '\0';
-   return true;
+  while (c != '\0') {
+    if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) {
+      return false;
+    }
+    if (i < size - 1) {
+      buf[i] = c;
+    } else {
+      // smaller buffer
+      return false;
+    }
+    i++; addr++;
+  }
+  buf[i] = '\0';
+  return true;
 }
 
+#ifdef __APPLE__
+#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
+// mangled name of Arguments::SharedArchivePath
+#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
+#else
 #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
 // mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
+#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
+#endif // __APPLE_
 
 static bool init_classsharing_workaround(struct ps_prochandle* ph) {
-   lib_info* lib = ph->libs;
-   while (lib != NULL) {
-      // we are iterating over shared objects from the core dump. look for
-      // libjvm[_g].so.
-      const char *jvm_name = 0;
-      if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 ||
-          (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) {
-         char classes_jsa[PATH_MAX];
-         struct FileMapHeader header;
-         size_t n = 0;
-         int fd = -1, m = 0;
-         uintptr_t base = 0, useSharedSpacesAddr = 0;
-         uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
-         jboolean useSharedSpaces = 0;
-
-         memset(classes_jsa, 0, sizeof(classes_jsa));
-         jvm_name = lib->name;
-         useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
-         if (useSharedSpacesAddr == 0) {
-            print_debug("can't lookup 'UseSharedSpaces' flag\n");
-            return false;
-         }
+  int m;
+  size_t n;
+  lib_info* lib = ph->libs;
+  while (lib != NULL) {
+    // we are iterating over shared objects from the core dump. look for
+    // libjvm[_g].so.
+    const char *jvm_name = 0;
+#ifdef __APPLE__
+    if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0 ||
+        (jvm_name = strstr(lib->name, "/libjvm_g.dylib")) != 0)
+#else
+    if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 ||
+        (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0)
+#endif // __APPLE__
+    {
+      char classes_jsa[PATH_MAX];
+      struct FileMapHeader header;
+      int fd = -1;
+      uintptr_t base = 0, useSharedSpacesAddr = 0;
+      uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
+      jboolean useSharedSpaces = 0;
 
-         // Hotspot vm types are not exported to build this library. So
-         // using equivalent type jboolean to read the value of
-         // UseSharedSpaces which is same as hotspot type "bool".
-         if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
-            print_debug("can't read the value of 'UseSharedSpaces' flag\n");
-            return false;
-         }
+      memset(classes_jsa, 0, sizeof(classes_jsa));
+      jvm_name = lib->name;
+      useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
+      if (useSharedSpacesAddr == 0) {
+        print_debug("can't lookup 'UseSharedSpaces' flag\n");
+        return false;
+      }
 
-         if ((int)useSharedSpaces == 0) {
-            print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
-            return true;
-         }
+      // Hotspot vm types are not exported to build this library. So
+      // using equivalent type jboolean to read the value of
+      // UseSharedSpaces which is same as hotspot type "bool".
+      if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
+        print_debug("can't read the value of 'UseSharedSpaces' flag\n");
+        return false;
+      }
 
-         sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
-         if (sharedArchivePathAddrAddr == 0) {
-            print_debug("can't lookup shared archive path symbol\n");
-            return false;
-         }
+      if ((int)useSharedSpaces == 0) {
+        print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
+        return true;
+      }
 
-         if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
-            print_debug("can't read shared archive path pointer\n");
-            return false;
-         }
+      sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
+      if (sharedArchivePathAddrAddr == 0) {
+        print_debug("can't lookup shared archive path symbol\n");
+        return false;
+      }
 
-         if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
-            print_debug("can't read shared archive path value\n");
-            return false;
-         }
+      if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
+        print_debug("can't read shared archive path pointer\n");
+        return false;
+      }
 
-         print_debug("looking for %s\n", classes_jsa);
-         // open the class sharing archive file
-         fd = pathmap_open(classes_jsa);
-         if (fd < 0) {
-            print_debug("can't open %s!\n", classes_jsa);
-            ph->core->classes_jsa_fd = -1;
-            return false;
-         } else {
-            print_debug("opened %s\n", classes_jsa);
-         }
+      if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
+        print_debug("can't read shared archive path value\n");
+        return false;
+      }
 
-         // read FileMapHeader from the file
-         memset(&header, 0, sizeof(struct FileMapHeader));
-         if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
-              != sizeof(struct FileMapHeader)) {
-            print_debug("can't read shared archive file map header from %s\n", classes_jsa);
-            close(fd);
-            return false;
-         }
+      print_debug("looking for %s\n", classes_jsa);
+      // open the class sharing archive file
+      fd = pathmap_open(classes_jsa);
+      if (fd < 0) {
+        print_debug("can't open %s!\n", classes_jsa);
+        ph->core->classes_jsa_fd = -1;
+        return false;
+      } else {
+        print_debug("opened %s\n", classes_jsa);
+      }
 
-         // check file magic
-         if (header._magic != 0xf00baba2) {
-            print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
-                        classes_jsa, header._magic);
-            close(fd);
-            return false;
-         }
+      // read FileMapHeader from the file
+      memset(&header, 0, sizeof(struct FileMapHeader));
+      if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
+           != sizeof(struct FileMapHeader)) {
+        print_debug("can't read shared archive file map header from %s\n", classes_jsa);
+        close(fd);
+        return false;
+      }
 
-         // check version
-         if (header._version != CURRENT_ARCHIVE_VERSION) {
-            print_debug("%s has wrong shared archive file version %d, expecting %d\n",
-                        classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
-            close(fd);
-            return false;
-         }
+      // check file magic
+      if (header._magic != 0xf00baba2) {
+        print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
+                     classes_jsa, header._magic);
+        close(fd);
+        return false;
+      }
+
+      // check version
+      if (header._version != CURRENT_ARCHIVE_VERSION) {
+        print_debug("%s has wrong shared archive file version %d, expecting %d\n",
+                     classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
+        close(fd);
+        return false;
+      }
 
-         ph->core->classes_jsa_fd = fd;
-         // add read-only maps from classes[_g].jsa to the list of maps
-         for (m = 0; m < NUM_SHARED_MAPS; m++) {
-            if (header._space[m]._read_only) {
-               base = (uintptr_t) header._space[m]._base;
-               // no need to worry about the fractional pages at-the-end.
-               // possible fractional pages are handled by core_read_data.
-               add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
-                         base, (size_t) header._space[m]._used);
-               print_debug("added a share archive map at 0x%lx\n", base);
-            }
-         }
-         return true;
+      ph->core->classes_jsa_fd = fd;
+      // add read-only maps from classes[_g].jsa to the list of maps
+      for (m = 0; m < NUM_SHARED_MAPS; m++) {
+        if (header._space[m]._read_only) {
+          base = (uintptr_t) header._space[m]._base;
+          // no need to worry about the fractional pages at-the-end.
+          // possible fractional pages are handled by core_read_data.
+          add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
+                                   base, (size_t) header._space[m]._used);
+          print_debug("added a share archive map at 0x%lx\n", base);
+        }
       }
-      lib = lib->next;
-   }
-   return true;
+      return true;
+    }
+    lib = lib->next;
+  }
+  return true;
 }
 
-
 //---------------------------------------------------------------------------
 // functions to handle map_info
 
@@ -397,54 +414,57 @@
 // callback for sorting the array of map_info pointers.
 static int core_cmp_mapping(const void *lhsp, const void *rhsp)
 {
-   const map_info *lhs = *((const map_info **)lhsp);
-   const map_info *rhs = *((const map_info **)rhsp);
+  const map_info *lhs = *((const map_info **)lhsp);
+  const map_info *rhs = *((const map_info **)rhsp);
 
-   if (lhs->vaddr == rhs->vaddr)
-      return (0);
+  if (lhs->vaddr == rhs->vaddr) {
+    return (0);
+  }
 
-   return (lhs->vaddr < rhs->vaddr ? -1 : 1);
+  return (lhs->vaddr < rhs->vaddr ? -1 : 1);
 }
 
 // we sort map_info by starting virtual address so that we can do
 // binary search to read from an address.
 static bool sort_map_array(struct ps_prochandle* ph) {
-   size_t num_maps = ph->core->num_maps;
-   map_info* map = ph->core->maps;
-   int i = 0;
+  size_t num_maps = ph->core->num_maps;
+  map_info* map = ph->core->maps;
+  int i = 0;
 
-   // allocate map_array
-   map_info** array;
-   if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) {
-      print_debug("can't allocate memory for map array\n");
-      return false;
-   }
+  // allocate map_array
+  map_info** array;
+  if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) {
+     print_debug("can't allocate memory for map array\n");
+     return false;
+  }
 
-   // add maps to array
-   while (map) {
-      array[i] = map;
-      i++;
-      map = map->next;
-   }
+  // add maps to array
+  while (map) {
+    array[i] = map;
+    i++;
+    map = map->next;
+  }
 
-   // sort is called twice. If this is second time, clear map array
-   if (ph->core->map_array) free(ph->core->map_array);
-   ph->core->map_array = array;
-   // sort the map_info array by base virtual address.
-   qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
-            core_cmp_mapping);
+  // sort is called twice. If this is second time, clear map array
+  if (ph->core->map_array) {
+    free(ph->core->map_array);
+  }
+  ph->core->map_array = array;
+  // sort the map_info array by base virtual address.
+  qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
+           core_cmp_mapping);
 
-   // print map
-   if (is_debug()) {
-      int j = 0;
-      print_debug("---- sorted virtual address map ----\n");
-      for (j = 0; j < ph->core->num_maps; j++) {
-        print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
-                                         ph->core->map_array[j]->memsz);
-      }
-   }
+  // print map
+  if (is_debug()) {
+    int j = 0;
+    print_debug("---- sorted virtual address map ----\n");
+    for (j = 0; j < ph->core->num_maps; j++) {
+      print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
+                                       ph->core->map_array[j]->memsz);
+    }
+  }
 
-   return true;
+  return true;
 }
 
 #ifndef MIN
@@ -461,16 +481,18 @@
       off_t off;
       int fd;
 
-      if (mp == NULL)
+      if (mp == NULL) {
          break;  /* No mapping for this address */
+      }
 
       fd = mp->fd;
       mapoff = addr - mp->vaddr;
       len = MIN(resid, mp->memsz - mapoff);
       off = mp->offset + mapoff;
 
-      if ((len = pread(fd, buf, len, off)) <= 0)
+      if ((len = pread(fd, buf, len, off)) <= 0) {
          break;
+      }
 
       resid -= len;
       addr += len;
@@ -507,8 +529,8 @@
 
 static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id,
                           struct reg* regs) {
-   // for core we have cached the lwp regs from NOTE section
-   thread_info* thr = ph->threads;
+   // for core we have cached the lwp regs after segment parsed
+   sa_thread_info* thr = ph->threads;
    while (thr) {
      if (thr->lwp_id == lwp_id) {
        memcpy(regs, &thr->regs, sizeof(struct reg));
@@ -519,7 +541,7 @@
    return false;
 }
 
-static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
+static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t id, void *info) {
    print_debug("core_get_lwp_info not implemented\n");
    return false;
 }
@@ -532,12 +554,451 @@
    .get_lwp_info= core_get_lwp_info
 };
 
-// read regs and create thread from NT_PRSTATUS entries from core file
+// from this point, mainly two blocks divided by def __APPLE__
+// one for Macosx, the other for regular Bsd
+
+#ifdef __APPLE__
+
+void print_thread(sa_thread_info *threadinfo) {
+  print_debug("thread added: %d\n", threadinfo->lwp_id);
+  print_debug("registers:\n");
+  print_debug("  r_r15: 0x%" PRIx64 "\n", threadinfo->regs.r_r15);
+  print_debug("  r_r14: 0x%" PRIx64 "\n", threadinfo->regs.r_r14);
+  print_debug("  r_r13: 0x%" PRIx64 "\n", threadinfo->regs.r_r13);
+  print_debug("  r_r12: 0x%" PRIx64 "\n", threadinfo->regs.r_r12);
+  print_debug("  r_r11: 0x%" PRIx64 "\n", threadinfo->regs.r_r11);
+  print_debug("  r_r10: 0x%" PRIx64 "\n", threadinfo->regs.r_r10);
+  print_debug("  r_r9:  0x%" PRIx64 "\n", threadinfo->regs.r_r9);
+  print_debug("  r_r8:  0x%" PRIx64 "\n", threadinfo->regs.r_r8);
+  print_debug("  r_rdi: 0x%" PRIx64 "\n", threadinfo->regs.r_rdi);
+  print_debug("  r_rsi: 0x%" PRIx64 "\n", threadinfo->regs.r_rsi);
+  print_debug("  r_rbp: 0x%" PRIx64 "\n", threadinfo->regs.r_rbp);
+  print_debug("  r_rbx: 0x%" PRIx64 "\n", threadinfo->regs.r_rbx);
+  print_debug("  r_rdx: 0x%" PRIx64 "\n", threadinfo->regs.r_rdx);
+  print_debug("  r_rcx: 0x%" PRIx64 "\n", threadinfo->regs.r_rcx);
+  print_debug("  r_rax: 0x%" PRIx64 "\n", threadinfo->regs.r_rax);
+  print_debug("  r_fs:  0x%" PRIx32 "\n", threadinfo->regs.r_fs);
+  print_debug("  r_gs:  0x%" PRIx32 "\n", threadinfo->regs.r_gs);
+  print_debug("  r_rip  0x%" PRIx64 "\n", threadinfo->regs.r_rip);
+  print_debug("  r_cs:  0x%" PRIx64 "\n", threadinfo->regs.r_cs);
+  print_debug("  r_rsp: 0x%" PRIx64 "\n", threadinfo->regs.r_rsp);
+  print_debug("  r_rflags: 0x%" PRIx64 "\n", threadinfo->regs.r_rflags);
+}
+
+// read all segments64 commands from core file
+// read all thread commands from core file
+static bool read_core_segments(struct ps_prochandle* ph) {
+  int i = 0;
+  int num_threads = 0;
+  int fd = ph->core->core_fd;
+  off_t offset = 0;
+  mach_header_64      fhead;
+  load_command        lcmd;
+  segment_command_64  segcmd;
+  // thread_command      thrcmd;
+
+  lseek(fd, offset, SEEK_SET);
+  if(read(fd, (void *)&fhead, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
+     goto err;
+  }
+  print_debug("total commands: %d\n", fhead.ncmds);
+  offset += sizeof(mach_header_64);
+  for (i = 0; i < fhead.ncmds; i++) {
+    lseek(fd, offset, SEEK_SET);
+    if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
+      goto err;
+    }
+    offset += lcmd.cmdsize;    // next command position
+    if (lcmd.cmd == LC_SEGMENT_64) {
+      lseek(fd, -sizeof(load_command), SEEK_CUR);
+      if (read(fd, (void *)&segcmd, sizeof(segment_command_64)) != sizeof(segment_command_64)) {
+        print_debug("failed to read LC_SEGMENT_64 i = %d!\n", i);
+        goto err;
+      }
+      if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize) == NULL) {
+        print_debug("Failed to add map_info at i = %d\n", i);
+        goto err;
+      }
+      print_debug("segment added: %" PRIu64 " 0x%" PRIx64 " %d\n",
+                   segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize);
+    } else if (lcmd.cmd == LC_THREAD || lcmd.cmd == LC_UNIXTHREAD) {
+      typedef struct thread_fc {
+        uint32_t  flavor;
+        uint32_t  count;
+      } thread_fc;
+      thread_fc fc;
+      uint32_t size = sizeof(load_command);
+      while (size < lcmd.cmdsize) {
+        if (read(fd, (void *)&fc, sizeof(thread_fc)) != sizeof(thread_fc)) {
+          printf("Reading flavor, count failed.\n");
+          goto err;
+        }
+        size += sizeof(thread_fc);
+        if (fc.flavor == x86_THREAD_STATE) {
+          x86_thread_state_t thrstate;
+          if (read(fd, (void *)&thrstate, sizeof(x86_thread_state_t)) != sizeof(x86_thread_state_t)) {
+            printf("Reading flavor, count failed.\n");
+            goto err;
+          }
+          size += sizeof(x86_thread_state_t);
+          // create thread info list, update lwp_id later
+          sa_thread_info* newthr = add_thread_info(ph, (pthread_t) -1, (lwpid_t) num_threads++);
+          if (newthr == NULL) {
+            printf("create thread_info failed\n");
+            goto err;
+          }
+
+          // note __DARWIN_UNIX03 depengs on other definitions
+#if __DARWIN_UNIX03
+#define get_register_v(regst, regname) \
+  regst.uts.ts64.__##regname
+#else
+#define get_register_v(regst, regname) \
+  regst.uts.ts64.##regname
+#endif // __DARWIN_UNIX03
+          newthr->regs.r_rax = get_register_v(thrstate, rax);
+          newthr->regs.r_rbx = get_register_v(thrstate, rbx);
+          newthr->regs.r_rcx = get_register_v(thrstate, rcx);
+          newthr->regs.r_rdx = get_register_v(thrstate, rdx);
+          newthr->regs.r_rdi = get_register_v(thrstate, rdi);
+          newthr->regs.r_rsi = get_register_v(thrstate, rsi);
+          newthr->regs.r_rbp = get_register_v(thrstate, rbp);
+          newthr->regs.r_rsp = get_register_v(thrstate, rsp);
+          newthr->regs.r_r8  = get_register_v(thrstate, r8);
+          newthr->regs.r_r9  = get_register_v(thrstate, r9);
+          newthr->regs.r_r10 = get_register_v(thrstate, r10);
+          newthr->regs.r_r11 = get_register_v(thrstate, r11);
+          newthr->regs.r_r12 = get_register_v(thrstate, r12);
+          newthr->regs.r_r13 = get_register_v(thrstate, r13);
+          newthr->regs.r_r14 = get_register_v(thrstate, r14);
+          newthr->regs.r_r15 = get_register_v(thrstate, r15);
+          newthr->regs.r_rip = get_register_v(thrstate, rip);
+          newthr->regs.r_rflags = get_register_v(thrstate, rflags);
+          newthr->regs.r_cs  = get_register_v(thrstate, cs);
+          newthr->regs.r_fs  = get_register_v(thrstate, fs);
+          newthr->regs.r_gs  = get_register_v(thrstate, gs);
+          print_thread(newthr);
+        } else if (fc.flavor == x86_FLOAT_STATE) {
+          x86_float_state_t flstate;
+          if (read(fd, (void *)&flstate, sizeof(x86_float_state_t)) != sizeof(x86_float_state_t)) {
+            print_debug("Reading flavor, count failed.\n");
+            goto err;
+          }
+          size += sizeof(x86_float_state_t);
+        } else if (fc.flavor == x86_EXCEPTION_STATE) {
+          x86_exception_state_t excpstate;
+          if (read(fd, (void *)&excpstate, sizeof(x86_exception_state_t)) != sizeof(x86_exception_state_t)) {
+            printf("Reading flavor, count failed.\n");
+            goto err;
+          }
+          size += sizeof(x86_exception_state_t);
+        }
+      }
+    }
+  }
+  return true;
+err:
+  return false;
+}
+
+/**local function **/
+bool exists(const char *fname)
+{
+  int fd;
+  if ((fd = open(fname, O_RDONLY)) > 0) {
+    close(fd);
+    return true;
+  }
+  return false;
+}
+
+// we check: 1. lib
+//           2. lib/server
+//           3. jre/lib
+//           4. jre/lib/server
+// from: 1. exe path
+//       2. JAVA_HOME
+//       3. DYLD_LIBRARY_PATH
+static bool get_real_path(struct ps_prochandle* ph, char *rpath) {
+  /** check if they exist in JAVA ***/
+  char* execname = ph->core->exec_path;
+  char  filepath[4096];
+  char* filename = strrchr(rpath, '/');               // like /libjvm.dylib
+  if (filename == NULL) {
+    return false;
+  }
+
+  char* posbin = strstr(execname, "/bin/java");
+  if (posbin != NULL) {
+    memcpy(filepath, execname, posbin - execname);    // not include trailing '/'
+    filepath[posbin - execname] = '\0';
+  } else {
+    char* java_home = getenv("JAVA_HOME");
+    if (java_home != NULL) {
+      strcpy(filepath, java_home);
+    } else {
+      char* dyldpath = getenv("DYLD_LIBRARY_PATH");
+      char* dypath = strtok(dyldpath, ":");
+      while (dypath != NULL) {
+        strcpy(filepath, dypath);
+        strcat(filepath, filename);
+        if (exists(filepath)) {
+           strcpy(rpath, filepath);
+           return true;
+        }
+        dypath = strtok(dyldpath, ":");
+      }
+      // not found
+      return false;
+    }
+  }
+  // for exec and java_home, jdkpath now is filepath
+  size_t filepath_base_size = strlen(filepath);
+
+  // first try /lib/ and /lib/server
+  strcat(filepath, "/lib");
+  strcat(filepath, filename);
+  if (exists(filepath)) {
+    strcpy(rpath, filepath);
+    return true;
+  }
+  char* pos = strstr(filepath, filename);    // like /libjvm.dylib
+  *pos = '\0';
+  strcat(filepath, "/server");
+  strcat(filepath, filename);
+  if (exists(filepath)) {
+    strcpy(rpath, filepath);
+    return true;
+  }
+
+  // then try /jre/lib/ and /jre/lib/server
+  filepath[filepath_base_size] = '\0';
+  strcat(filepath, "/jre/lib");
+  strcat(filepath, filename);
+  if (exists(filepath)) {
+    strcpy(rpath, filepath);
+    return true;
+  }
+  pos = strstr(filepath, filename);
+  *pos = '\0';
+  strcat(filepath, "/server");
+  strcat(filepath, filename);
+  if (exists(filepath)) {
+    strcpy(rpath, filepath);
+    return true;
+  }
+
+  return false;
+}
+
+static bool read_shared_lib_info(struct ps_prochandle* ph) {
+  static int pagesize = 0;
+  int fd = ph->core->core_fd;
+  int i = 0, j;
+  uint32_t  v;
+  mach_header_64 header;        // used to check if a file header in segment
+  load_command lcmd;
+  dylib_command dylibcmd;
+
+  char name[BUF_SIZE];  // use to store name
+
+  if (pagesize == 0) {
+    pagesize = getpagesize();
+    print_debug("page size is %d\n", pagesize);
+  }
+  for (j = 0; j < ph->core->num_maps; j++) {
+    map_info *iter = ph->core->map_array[j];   // head
+    off_t fpos = iter->offset;
+    if (iter->fd != fd) {
+      // only search core file!
+      continue;
+    }
+    print_debug("map_info %d: vmaddr = 0x%016" PRIx64 "  fileoff = %" PRIu64 "  vmsize = %" PRIu64 "\n",
+                           j, iter->vaddr, iter->offset, iter->memsz);
+    lseek(fd, fpos, SEEK_SET);
+    // we assume .dylib loaded at segment address --- which is true for JVM libraries
+    // multiple files may be loaded in one segment.
+    // if first word is not a magic word, means this segment does not contain lib file.
+    if (read(fd, (void *)&v, sizeof(uint32_t)) == sizeof(uint32_t)) {
+      if (v != MH_MAGIC_64) {
+        continue;
+      }
+    } else {
+      // may be encountered last map, which is not readable
+      continue;
+    }
+    while (ltell(fd) - iter->offset < iter->memsz) {
+      lseek(fd, fpos, SEEK_SET);
+      if (read(fd, (void *)&v, sizeof(uint32_t)) != sizeof(uint32_t)) {
+        break;
+      }
+      if (v != MH_MAGIC_64) {
+        fpos = (ltell(fd) + pagesize -1)/pagesize * pagesize;
+        continue;
+      }
+      lseek(fd, -sizeof(uint32_t), SEEK_CUR);
+      // this is the file begining to core file.
+      if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
+        goto err;
+      }
+      fpos = ltell(fd);
+
+      // found a mach-o file in this segment
+      for (i = 0; i < header.ncmds; i++) {
+        // read commands in this "file"
+        // LC_ID_DYLIB is the file itself for a .dylib
+        lseek(fd, fpos, SEEK_SET);
+        if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
+          return false;   // error
+        }
+        fpos += lcmd.cmdsize;  // next command position
+        // make sure still within seg size.
+        if (fpos  - lcmd.cmdsize - iter->offset > iter->memsz) {
+          print_debug("Warning: out of segement limit: %ld \n", fpos  - lcmd.cmdsize - iter->offset);
+          break;  // no need to iterate all commands
+        }
+        if (lcmd.cmd == LC_ID_DYLIB) {
+          lseek(fd, -sizeof(load_command), SEEK_CUR);
+          if (read(fd, (void *)&dylibcmd, sizeof(dylib_command)) != sizeof(dylib_command)) {
+            return false;
+          }
+          /**** name stored at dylib_command.dylib.name.offset, is a C string  */
+          lseek(fd, dylibcmd.dylib.name.offset - sizeof(dylib_command), SEEK_CUR);
+          int j = 0;
+          while (j < BUF_SIZE) {
+            read(fd, (void *)(name + j), sizeof(char));
+            if (name[j] == '\0') break;
+            j++;
+          }
+          print_debug("%s\n", name);
+          // changed name from @rpath/xxxx.dylib to real path
+          if (strrchr(name, '@')) {
+            get_real_path(ph, name);
+            print_debug("get_real_path returned: %s\n", name);
+          }
+          add_lib_info(ph, name, iter->vaddr);
+          break;
+        }
+      }
+      // done with the file, advanced to next page to search more files
+      fpos = (ltell(fd) + pagesize - 1) / pagesize * pagesize;
+    }
+  }
+  return true;
+err:
+  return false;
+}
+
+bool read_macho64_header(int fd, mach_header_64* core_header) {
+  bool is_macho = false;
+  if (fd < 0) return false;
+  off_t pos = ltell(fd);
+  lseek(fd, 0, SEEK_SET);
+  if (read(fd, (void *)core_header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
+    is_macho = false;
+  } else {
+    is_macho = (core_header->magic ==  MH_MAGIC_64 || core_header->magic ==  MH_CIGAM_64);
+  }
+  lseek(fd, pos, SEEK_SET);
+  return is_macho;
+}
+
+// the one and only one exposed stuff from this file
+struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
+  mach_header_64 core_header;
+  mach_header_64 exec_header;
+
+  struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
+  if (ph == NULL) {
+    print_debug("cant allocate ps_prochandle\n");
+    return NULL;
+  }
+
+  if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
+    free(ph);
+    print_debug("can't allocate ps_prochandle\n");
+    return NULL;
+  }
+
+  // initialize ph
+  ph->ops = &core_ops;
+  ph->core->core_fd   = -1;
+  ph->core->exec_fd   = -1;
+  ph->core->interp_fd = -1;
+
+  print_debug("exec: %s   core: %s", exec_file, core_file);
+
+  strncpy(ph->core->exec_path, exec_file, sizeof(ph->core->exec_path));
+
+  // open the core file
+  if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
+    print_error("can't open core file\n");
+    goto err;
+  }
+
+  // read core file header
+  if (read_macho64_header(ph->core->core_fd, &core_header) != true || core_header.filetype != MH_CORE) {
+    print_debug("core file is not a valid Mach-O file\n");
+    goto err;
+  }
+
+  if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
+    print_error("can't open executable file\n");
+    goto err;
+  }
+
+  if (read_macho64_header(ph->core->exec_fd, &exec_header) != true ||
+                          exec_header.filetype != MH_EXECUTE) {
+    print_error("executable file is not a valid Mach-O file\n");
+    goto err;
+  }
+
+  // process core file segments
+  if (read_core_segments(ph) != true) {
+    print_error("failed to read core segments\n");
+    goto err;
+  }
+
+  // allocate and sort maps into map_array, we need to do this
+  // here because read_shared_lib_info needs to read from debuggee
+  // address space
+  if (sort_map_array(ph) != true) {
+    print_error("failed to sort segment map array\n");
+    goto err;
+  }
+
+  if (read_shared_lib_info(ph) != true) {
+    print_error("failed to read libraries\n");
+    goto err;
+  }
+
+  // sort again because we have added more mappings from shared objects
+  if (sort_map_array(ph) != true) {
+    print_error("failed to sort segment map array\n");
+    goto err;
+  }
+
+  if (init_classsharing_workaround(ph) != true) {
+    print_error("failed to workaround classshareing\n");
+    goto err;
+  }
+
+  print_debug("Leave Pgrab_core\n");
+  return ph;
+
+err:
+  Prelease(ph);
+  return NULL;
+}
+
+#else // __APPLE__ (none macosx)
+
+// read regs and create thread from core file
 static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) {
    // we have to read prstatus_t from buf
    // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t");
    prstatus_t* prstat = (prstatus_t*) buf;
-   thread_info* newthr;
+   sa_thread_info* newthr;
    print_debug("got integer regset for lwp %d\n", prstat->pr_pid);
    // we set pthread_t to -1 for core dump
    if((newthr = add_thread_info(ph, (pthread_t) -1,  prstat->pr_pid)) == NULL)
@@ -632,8 +1093,9 @@
                                    notep->n_type, notep->n_descsz);
 
       if (notep->n_type == NT_PRSTATUS) {
-         if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true)
+         if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) {
             return false;
+         }
       }
       p = descdata + ROUNDUP(notep->n_descsz, 4);
    }
@@ -681,7 +1143,9 @@
     for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
       switch (core_php->p_type) {
          case PT_NOTE:
-            if (core_handle_note(ph, core_php) != true) goto err;
+            if (core_handle_note(ph, core_php) != true) {
+              goto err;
+            }
             break;
 
          case PT_LOAD: {
@@ -800,7 +1264,6 @@
    return false;
 }
 
-
 #define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug,  r_map)
 #define LD_BASE_OFFSET        offsetof(struct r_debug,  r_ldbase)
 #define LINK_MAP_ADDR_OFFSET  offsetof(struct link_map, l_addr)
@@ -810,213 +1273,218 @@
 // read shared library info from runtime linker's data structures.
 // This work is done by librtlb_db in Solaris
 static bool read_shared_lib_info(struct ps_prochandle* ph) {
-   uintptr_t addr = ph->core->dynamic_addr;
-   uintptr_t debug_base;
-   uintptr_t first_link_map_addr;
-   uintptr_t ld_base_addr;
-   uintptr_t link_map_addr;
-   uintptr_t lib_base_diff;
-   uintptr_t lib_base;
-   uintptr_t lib_name_addr;
-   char lib_name[BUF_SIZE];
-   ELF_DYN dyn;
-   ELF_EHDR elf_ehdr;
-   int lib_fd;
+  uintptr_t addr = ph->core->dynamic_addr;
+  uintptr_t debug_base;
+  uintptr_t first_link_map_addr;
+  uintptr_t ld_base_addr;
+  uintptr_t link_map_addr;
+  uintptr_t lib_base_diff;
+  uintptr_t lib_base;
+  uintptr_t lib_name_addr;
+  char lib_name[BUF_SIZE];
+  ELF_DYN dyn;
+  ELF_EHDR elf_ehdr;
+  int lib_fd;
 
-   // _DYNAMIC has information of the form
-   //         [tag] [data] [tag] [data] .....
-   // Both tag and data are pointer sized.
-   // We look for dynamic info with DT_DEBUG. This has shared object info.
-   // refer to struct r_debug in link.h
+  // _DYNAMIC has information of the form
+  //         [tag] [data] [tag] [data] .....
+  // Both tag and data are pointer sized.
+  // We look for dynamic info with DT_DEBUG. This has shared object info.
+  // refer to struct r_debug in link.h
 
-   dyn.d_tag = DT_NULL;
-   while (dyn.d_tag != DT_DEBUG) {
-      if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) {
-         print_debug("can't read debug info from _DYNAMIC\n");
-         return false;
-      }
-      addr += sizeof(ELF_DYN);
-   }
+  dyn.d_tag = DT_NULL;
+  while (dyn.d_tag != DT_DEBUG) {
+    if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) {
+      print_debug("can't read debug info from _DYNAMIC\n");
+      return false;
+    }
+    addr += sizeof(ELF_DYN);
+  }
 
-   // we have got Dyn entry with DT_DEBUG
-   debug_base = dyn.d_un.d_ptr;
-   // at debug_base we have struct r_debug. This has first link map in r_map field
-   if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET,
-                 &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) {
-      print_debug("can't read first link map address\n");
-      return false;
-   }
+  // we have got Dyn entry with DT_DEBUG
+  debug_base = dyn.d_un.d_ptr;
+  // at debug_base we have struct r_debug. This has first link map in r_map field
+  if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET,
+                  &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) {
+    print_debug("can't read first link map address\n");
+    return false;
+  }
 
-   // read ld_base address from struct r_debug
-   // XXX: There is no r_ldbase member on BSD
-/*
-   if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
-                 sizeof(uintptr_t)) != PS_OK) {
-      print_debug("can't read ld base address\n");
-      return false;
-   }
-   ph->core->ld_base_addr = ld_base_addr;
-*/
-   ph->core->ld_base_addr = 0;
+  // read ld_base address from struct r_debug
+  // XXX: There is no r_ldbase member on BSD
+  /*
+  if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
+                  sizeof(uintptr_t)) != PS_OK) {
+    print_debug("can't read ld base address\n");
+    return false;
+  }
+  ph->core->ld_base_addr = ld_base_addr;
+  */
+  ph->core->ld_base_addr = 0;
 
-   print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
+  print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
 
-   // now read segments from interp (i.e ld-elf.so.1)
-   if (read_interp_segments(ph) != true)
-      return false;
+  // now read segments from interp (i.e ld-elf.so.1)
+  if (read_interp_segments(ph) != true)
+    return false;
 
-   // after adding interpreter (ld.so) mappings sort again
-   if (sort_map_array(ph) != true)
-      return false;
+  // after adding interpreter (ld.so) mappings sort again
+  if (sort_map_array(ph) != true)
+    return false;
 
-   print_debug("first link map is at 0x%lx\n", first_link_map_addr);
+  print_debug("first link map is at 0x%lx\n", first_link_map_addr);
 
-   link_map_addr = first_link_map_addr;
-   while (link_map_addr != 0) {
-      // read library base address of the .so. Note that even though <sys/link.h> calls
-      // link_map->l_addr as "base address",  this is * not * really base virtual
-      // address of the shared object. This is actually the difference b/w the virtual
-      // address mentioned in shared object and the actual virtual base where runtime
-      // linker loaded it. We use "base diff" in read_lib_segments call below.
+  link_map_addr = first_link_map_addr;
+  while (link_map_addr != 0) {
+    // read library base address of the .so. Note that even though <sys/link.h> calls
+    // link_map->l_addr as "base address",  this is * not * really base virtual
+    // address of the shared object. This is actually the difference b/w the virtual
+    // address mentioned in shared object and the actual virtual base where runtime
+    // linker loaded it. We use "base diff" in read_lib_segments call below.
 
-      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET,
-                   &lib_base_diff, sizeof(uintptr_t)) != PS_OK) {
-         print_debug("can't read shared object base address diff\n");
-         return false;
-      }
+    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET,
+                 &lib_base_diff, sizeof(uintptr_t)) != PS_OK) {
+      print_debug("can't read shared object base address diff\n");
+      return false;
+    }
 
-      // read address of the name
-      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET,
-                    &lib_name_addr, sizeof(uintptr_t)) != PS_OK) {
-         print_debug("can't read address of shared object name\n");
-         return false;
-      }
+    // read address of the name
+    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET,
+                  &lib_name_addr, sizeof(uintptr_t)) != PS_OK) {
+      print_debug("can't read address of shared object name\n");
+      return false;
+    }
 
-      // read name of the shared object
-      if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) {
-         print_debug("can't read shared object name\n");
-         return false;
-      }
+    // read name of the shared object
+    if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) {
+      print_debug("can't read shared object name\n");
+      return false;
+    }
 
-      if (lib_name[0] != '\0') {
-         // ignore empty lib names
-         lib_fd = pathmap_open(lib_name);
+    if (lib_name[0] != '\0') {
+      // ignore empty lib names
+      lib_fd = pathmap_open(lib_name);
 
-         if (lib_fd < 0) {
-            print_debug("can't open shared object %s\n", lib_name);
-            // continue with other libraries...
-         } else {
-            if (read_elf_header(lib_fd, &elf_ehdr)) {
-               lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
-               print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
-                           lib_name, lib_base, lib_base_diff);
-               // while adding library mappings we need to use "base difference".
-               if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) {
-                  print_debug("can't read shared object's segments\n");
-                  close(lib_fd);
-                  return false;
-               }
-               add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
-               // Map info is added for the library (lib_name) so
-               // we need to re-sort it before calling the p_pdread.
-               if (sort_map_array(ph) != true)
-                  return false;
-            } else {
-               print_debug("can't read ELF header for shared object %s\n", lib_name);
-               close(lib_fd);
-               // continue with other libraries...
-            }
-         }
+      if (lib_fd < 0) {
+        print_debug("can't open shared object %s\n", lib_name);
+        // continue with other libraries...
+      } else {
+        if (read_elf_header(lib_fd, &elf_ehdr)) {
+          lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
+          print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
+                       lib_name, lib_base, lib_base_diff);
+          // while adding library mappings we need to use "base difference".
+          if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) {
+            print_debug("can't read shared object's segments\n");
+            close(lib_fd);
+            return false;
+          }
+          add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
+          // Map info is added for the library (lib_name) so
+          // we need to re-sort it before calling the p_pdread.
+          if (sort_map_array(ph) != true)
+            return false;
+        } else {
+          print_debug("can't read ELF header for shared object %s\n", lib_name);
+          close(lib_fd);
+          // continue with other libraries...
+        }
       }
+    }
 
-      // read next link_map address
-      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET,
-                        &link_map_addr, sizeof(uintptr_t)) != PS_OK) {
-         print_debug("can't read next link in link_map\n");
-         return false;
-      }
-   }
+    // read next link_map address
+    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET,
+                 &link_map_addr, sizeof(uintptr_t)) != PS_OK) {
+      print_debug("can't read next link in link_map\n");
+      return false;
+    }
+  }
 
-   return true;
+  return true;
 }
 
 // the one and only one exposed stuff from this file
 struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
-   ELF_EHDR core_ehdr;
-   ELF_EHDR exec_ehdr;
+  ELF_EHDR core_ehdr;
+  ELF_EHDR exec_ehdr;
 
-   struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
-   if (ph == NULL) {
-      print_debug("can't allocate ps_prochandle\n");
-      return NULL;
-   }
+  struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
+  if (ph == NULL) {
+    print_debug("cant allocate ps_prochandle\n");
+    return NULL;
+  }
 
-   if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
-      free(ph);
-      print_debug("can't allocate ps_prochandle\n");
-      return NULL;
-   }
+  if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
+    free(ph);
+    print_debug("can't allocate ps_prochandle\n");
+    return NULL;
+  }
 
-   // initialize ph
-   ph->ops = &core_ops;
-   ph->core->core_fd   = -1;
-   ph->core->exec_fd   = -1;
-   ph->core->interp_fd = -1;
+  // initialize ph
+  ph->ops = &core_ops;
+  ph->core->core_fd   = -1;
+  ph->core->exec_fd   = -1;
+  ph->core->interp_fd = -1;
+
+  print_debug("exec: %s   core: %s", exec_file, core_file);
 
-   // open the core file
-   if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
-      print_debug("can't open core file\n");
-      goto err;
-   }
+  // open the core file
+  if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
+    print_debug("can't open core file\n");
+    goto err;
+  }
 
-   // read core file ELF header
-   if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) {
-      print_debug("core file is not a valid ELF ET_CORE file\n");
-      goto err;
-   }
+  // read core file ELF header
+  if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) {
+    print_debug("core file is not a valid ELF ET_CORE file\n");
+    goto err;
+  }
 
-   if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
-      print_debug("can't open executable file\n");
-      goto err;
-   }
+  if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
+    print_debug("can't open executable file\n");
+    goto err;
+  }
 
-   if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) {
-      print_debug("executable file is not a valid ELF ET_EXEC file\n");
-      goto err;
-   }
+  if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) {
+     print_debug("executable file is not a valid ELF ET_EXEC file\n");
+     goto err;
+  }
 
-   // process core file segments
-   if (read_core_segments(ph, &core_ehdr) != true)
-      goto err;
+  // process core file segments
+  if (read_core_segments(ph, &core_ehdr) != true)
+     goto err;
 
-   // process exec file segments
-   if (read_exec_segments(ph, &exec_ehdr) != true)
-      goto err;
+  // process exec file segments
+  if (read_exec_segments(ph, &exec_ehdr) != true)
+     goto err;
 
-   // exec file is also treated like a shared object for symbol search
-   if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
-                       (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
-      goto err;
+  // exec file is also treated like a shared object for symbol search
+  if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
+                      (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
+     goto err;
 
-   // allocate and sort maps into map_array, we need to do this
-   // here because read_shared_lib_info needs to read from debuggee
-   // address space
-   if (sort_map_array(ph) != true)
-      goto err;
+  // allocate and sort maps into map_array, we need to do this
+  // here because read_shared_lib_info needs to read from debuggee
+  // address space
+  if (sort_map_array(ph) != true)
+    goto err;
 
-   if (read_shared_lib_info(ph) != true)
-      goto err;
+  if (read_shared_lib_info(ph) != true)
+    goto err;
 
-   // sort again because we have added more mappings from shared objects
-   if (sort_map_array(ph) != true)
-      goto err;
+  // sort again because we have added more mappings from shared objects
+  if (sort_map_array(ph) != true)
+    goto err;
 
-   if (init_classsharing_workaround(ph) != true)
-      goto err;
+  if (init_classsharing_workaround(ph) != true)
+    goto err;
 
-   return ph;
+  print_debug("Leave Pgrab_core\n");
+  return ph;
 
 err:
-   Prelease(ph);
-   return NULL;
+  Prelease(ph);
+  return NULL;
 }
+
+#endif // __APPLE__
--- a/agent/src/os/bsd/symtab.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/symtab.c	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -28,32 +28,182 @@
 #include <string.h>
 #include <db.h>
 #include <fcntl.h>
+
+#include "libproc_impl.h"
 #include "symtab.h"
+#ifndef __APPLE__
 #include "salibelf.h"
+#endif // __APPLE__
 
 
 // ----------------------------------------------------
 // functions for symbol lookups
 // ----------------------------------------------------
 
+typedef struct symtab_symbol {
+  char *name;                // name like __ZThread_...
+  uintptr_t offset;          // to loaded address
+  uintptr_t size;            // size strlen
+} symtab_symbol;
+
+typedef struct symtab {
+  char *strs;                // all symbols "__symbol1__'\0'__symbol2__...."
+  size_t num_symbols;
+  DB* hash_table;
+  symtab_symbol* symbols;
+} symtab_t;
+
+#ifdef __APPLE__
+
+void build_search_table(symtab_t *symtab) {
+  int i;
+  for (i = 0; i < symtab->num_symbols; i++) {
+    DBT key, value;
+    key.data = symtab->symbols[i].name;
+    key.size = strlen(key.data) + 1;
+    value.data = &(symtab->symbols[i]);
+    value.size = sizeof(symtab_symbol);
+    (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
+
+    // check result
+    if (is_debug()) {
+      DBT rkey, rvalue;
+      char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1);
+      strcpy(tmp, symtab->symbols[i].name);
+      rkey.data = tmp;
+      rkey.size = strlen(tmp) + 1;
+      (*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0);
+      // we may get a copy back so compare contents
+      symtab_symbol *res = (symtab_symbol *)rvalue.data;
+      if (strcmp(res->name, symtab->symbols[i].name)  ||
+          res->offset != symtab->symbols[i].offset    ||
+          res->size != symtab->symbols[i].size) {
+        print_debug("error to get hash_table value!\n");
+      }
+      free(tmp);
+    }
+  }
+}
+
+// read symbol table from given fd.
+struct symtab* build_symtab(int fd) {
+  symtab_t* symtab = NULL;
+  int i;
+  mach_header_64 header;
+  off_t image_start;
+
+  if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
+    print_debug("failed in get fat header\n");
+    return NULL;
+  }
+  lseek(fd, image_start, SEEK_SET);
+  if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
+    print_debug("reading header failed!\n");
+    return NULL;
+  }
+  // header
+  if (header.magic != MH_MAGIC_64) {
+    print_debug("not a valid .dylib file\n");
+    return NULL;
+  }
+
+  load_command lcmd;
+  symtab_command symtabcmd;
+  nlist_64 lentry;
+
+  bool lcsymtab_exist = false;
+
+  long filepos = ltell(fd);
+  for (i = 0; i < header.ncmds; i++) {
+    lseek(fd, filepos, SEEK_SET);
+    if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
+      print_debug("read load_command failed for file\n");
+      return NULL;
+    }
+    filepos += lcmd.cmdsize;  // next command position
+    if (lcmd.cmd == LC_SYMTAB) {
+      lseek(fd, -sizeof(load_command), SEEK_CUR);
+      lcsymtab_exist = true;
+      break;
+    }
+  }
+  if (!lcsymtab_exist) {
+    print_debug("No symtab command found!\n");
+    return NULL;
+  }
+  if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) {
+    print_debug("read symtab_command failed for file");
+    return NULL;
+  }
+  symtab = (symtab_t *)malloc(sizeof(symtab_t));
+  if (symtab == NULL) {
+    print_debug("out of memory: allocating symtab\n");
+    return NULL;
+  }
+
+  // create hash table, we use berkeley db to
+  // manipulate the hash table.
+  symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
+  if (symtab->hash_table == NULL)
+    goto quit;
+
+  symtab->num_symbols = symtabcmd.nsyms;
+  symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols);
+  symtab->strs    = (char *)malloc(sizeof(char) * symtabcmd.strsize);
+  if (symtab->symbols == NULL || symtab->strs == NULL) {
+     print_debug("out of memory: allocating symtab.symbol or symtab.strs\n");
+     goto quit;
+  }
+  lseek(fd, image_start + symtabcmd.symoff, SEEK_SET);
+  for (i = 0; i < symtab->num_symbols; i++) {
+    if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) {
+      print_debug("read nlist_64 failed at %i\n", i);
+      goto quit;
+    }
+    symtab->symbols[i].offset = lentry.n_value;
+    symtab->symbols[i].size  = lentry.n_un.n_strx;        // index
+  }
+
+  // string table
+  lseek(fd, image_start + symtabcmd.stroff, SEEK_SET);
+  int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char));
+  if (size != symtabcmd.strsize * sizeof(char)) {
+     print_debug("reading string table failed\n");
+     goto quit;
+  }
+
+  for (i = 0; i < symtab->num_symbols; i++) {
+    symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size;
+    if (i > 0) {
+      // fix size
+      symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size;
+      print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size);
+
+    }
+
+    if (i == symtab->num_symbols - 1) {
+      // last index
+      symtab->symbols[i].size =
+            symtabcmd.strsize - symtab->symbols[i].size;
+      print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size);
+    }
+  }
+
+  // build a hashtable for fast query
+  build_search_table(symtab);
+  return symtab;
+quit:
+  if (symtab) destroy_symtab(symtab);
+  return NULL;
+}
+
+#else // __APPLE__
+
 struct elf_section {
   ELF_SHDR   *c_shdr;
   void       *c_data;
 };
 
-struct elf_symbol {
-  char *name;
-  uintptr_t offset;
-  uintptr_t size;
-};
-
-typedef struct symtab {
-  char *strs;
-  size_t num_symbols;
-  struct elf_symbol *symbols;
-  DB* hash_table;
-} symtab_t;
-
 // read symbol table from given fd.
 struct symtab* build_symtab(int fd) {
   ELF_EHDR ehdr;
@@ -176,7 +326,7 @@
         key.data = sym_name;
         key.size = strlen(sym_name) + 1;
         value.data = &(symtab->symbols[j]);
-        value.size = sizeof(void *);
+        value.size = sizeof(symtab_symbol);
         (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
       }
     }
@@ -201,30 +351,29 @@
   return symtab;
 }
 
-void destroy_symtab(struct symtab* symtab) {
+#endif // __APPLE__
+
+void destroy_symtab(symtab_t* symtab) {
   if (!symtab) return;
-  if (symtab->strs) free(symtab->strs);
-  if (symtab->symbols) free(symtab->symbols);
-  if (symtab->hash_table) {
-    (*symtab->hash_table->close)(symtab->hash_table);
-  }
+  free(symtab->strs);
+  free(symtab->symbols);
   free(symtab);
 }
 
-uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
-                      const char *sym_name, int *sym_size) {
+uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) {
   DBT key, value;
   int ret;
 
   // library does not have symbol table
-  if (!symtab || !symtab->hash_table)
+  if (!symtab || !symtab->hash_table) {
      return 0;
+  }
 
   key.data = (char*)(uintptr_t)sym_name;
   key.size = strlen(sym_name) + 1;
   ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
   if (ret == 0) {
-    struct elf_symbol *sym = value.data;
+    symtab_symbol *sym = value.data;
     uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
     if (sym_size) *sym_size = sym->size;
     return rslt;
@@ -238,7 +387,7 @@
   int n = 0;
   if (!symtab) return NULL;
   for (; n < symtab->num_symbols; n++) {
-    struct elf_symbol* sym = &(symtab->symbols[n]);
+    symtab_symbol* sym = &(symtab->symbols[n]);
     if (sym->name != NULL &&
       offset >= sym->offset && offset < sym->offset + sym->size) {
       if (poffset) *poffset = (offset - sym->offset);
--- a/agent/src/os/bsd/symtab.h	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/bsd/symtab.h	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -27,11 +27,11 @@
 
 #include <stdint.h>
 
-// interface to manage ELF symbol tables
+// interface to manage ELF or MachO symbol tables
 
 struct symtab;
 
-// build symbol table for a given ELF file descriptor
+// build symbol table for a given ELF or MachO file escriptor
 struct symtab* build_symtab(int fd);
 
 // destroy the symbol table
--- a/agent/src/os/linux/LinuxDebuggerLocal.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/linux/LinuxDebuggerLocal.c	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -25,6 +25,13 @@
 #include <jni.h>
 #include "libproc.h"
 
+#include <elf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+
 #if defined(x86_64) && !defined(amd64)
 #define amd64 1
 #endif
@@ -154,6 +161,39 @@
   }
 }
 
+
+/*
+ * Verify that a named ELF binary file (core or executable) has the same
+ * bitness as ourselves.
+ * Throw an exception if there is a mismatch or other problem.
+ *
+ * If we proceed using a mismatched debugger/debuggee, the best to hope
+ * for is a missing symbol, the worst is a crash searching for debug symbols.
+ */
+void verifyBitness(JNIEnv *env, const char *binaryName) {
+  int fd = open(binaryName, O_RDONLY);
+  if (fd < 0) {
+    THROW_NEW_DEBUGGER_EXCEPTION("cannot open binary file");
+  }
+  unsigned char elf_ident[EI_NIDENT];
+  int i = read(fd, &elf_ident, sizeof(elf_ident));
+  close(fd);
+
+  if (i < 0) {
+    THROW_NEW_DEBUGGER_EXCEPTION("cannot read binary file");
+  }
+#ifndef _LP64
+  if (elf_ident[EI_CLASS] == ELFCLASS64) {
+    THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use 64-bit java for debugger");
+  }
+#else
+  if (elf_ident[EI_CLASS] != ELFCLASS64) {
+    THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger");
+  }
+#endif
+}
+
+
 /*
  * Class:     sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
  * Method:    attach0
@@ -162,6 +202,12 @@
 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I
   (JNIEnv *env, jobject this_obj, jint jpid) {
 
+  // For bitness checking, locate binary at /proc/jpid/exe
+  char buf[PATH_MAX];
+  snprintf((char *) &buf, PATH_MAX, "/proc/%d/exe", jpid);
+  verifyBitness(env, (char *) &buf);
+  CHECK_EXCEPTION;
+
   struct ps_prochandle* ph;
   if ( (ph = Pgrab(jpid)) == NULL) {
     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
@@ -187,6 +233,9 @@
   coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
   CHECK_EXCEPTION;
 
+  verifyBitness(env, execName_cstr);
+  CHECK_EXCEPTION;
+
   if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
     (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
     (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
--- a/agent/src/os/linux/ps_core.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/os/linux/ps_core.c	Mon Apr 15 08:51:19 2013 +0200
@@ -132,12 +132,12 @@
 }
 
 // Part of the class sharing workaround
-static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
+static void add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
                              uintptr_t vaddr, size_t memsz) {
    map_info* map;
    if ((map = allocate_init_map(ph->core->classes_jsa_fd,
                                 offset, vaddr, memsz)) == NULL) {
-      return NULL;
+      return;
    }
 
    map->next = ph->core->class_share_maps;
--- a/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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,11 +34,18 @@
   public BsdVtblAccess(SymbolLookup symbolLookup,
                          String[] dllNames) {
     super(symbolLookup, dllNames);
-
-    if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null ||
-        symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) {
+    boolean oldVT = false;
+    boolean isDarwin = dllNames[0].lastIndexOf(".dylib") != -1;
+    String vtJavaThread = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
+    for (String dllName : dllNames) {
+       if (symbolLookup.lookup(dllName, vtJavaThread) != null) {
+         oldVT = true;
+         break;
+       }
+    }
+    if (oldVT) {
        // old C++ ABI
-       vt = "__vt_";
+       vt = isDarwin ? "_vt_" :  "__vt_";
     } else {
        // new C++ ABI
        vt = "_ZTV";
--- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,36 +24,81 @@
 
 package sun.jvm.hotspot;
 
-import java.io.*;
-import java.math.*;
-import java.util.*;
-import java.util.regex.*;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import sun.jvm.hotspot.types.Type;
-import sun.jvm.hotspot.types.Field;
-import sun.jvm.hotspot.HotSpotTypeDataBase;
-import sun.jvm.hotspot.types.basic.BasicType;
-import sun.jvm.hotspot.types.basic.BasicTypeDataBase;
-import sun.jvm.hotspot.types.CIntegerType;
-import sun.jvm.hotspot.code.*;
-import sun.jvm.hotspot.compiler.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.interpreter.*;
-import sun.jvm.hotspot.memory.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.opto.*;
-import sun.jvm.hotspot.ci.*;
-import sun.jvm.hotspot.asm.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-import sun.jvm.hotspot.utilities.soql.*;
-import sun.jvm.hotspot.ui.classbrowser.*;
-import sun.jvm.hotspot.ui.tree.*;
-import sun.jvm.hotspot.tools.*;
+import sun.jvm.hotspot.ci.ciEnv;
+import sun.jvm.hotspot.code.CodeBlob;
+import sun.jvm.hotspot.code.CodeCacheVisitor;
+import sun.jvm.hotspot.code.NMethod;
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.debugger.OopHandle;
+import sun.jvm.hotspot.memory.SymbolTable;
+import sun.jvm.hotspot.memory.SystemDictionary;
+import sun.jvm.hotspot.memory.Universe;
+import sun.jvm.hotspot.oops.DefaultHeapVisitor;
+import sun.jvm.hotspot.oops.HeapVisitor;
+import sun.jvm.hotspot.oops.InstanceKlass;
+import sun.jvm.hotspot.oops.Klass;
+import sun.jvm.hotspot.oops.Metadata;
+import sun.jvm.hotspot.oops.Method;
+import sun.jvm.hotspot.oops.MethodData;
+import sun.jvm.hotspot.oops.Oop;
+import sun.jvm.hotspot.oops.RawHeapVisitor;
+import sun.jvm.hotspot.oops.Symbol;
+import sun.jvm.hotspot.oops.UnknownOopException;
+import sun.jvm.hotspot.opto.Compile;
+import sun.jvm.hotspot.opto.InlineTree;
+import sun.jvm.hotspot.runtime.CompiledVFrame;
+import sun.jvm.hotspot.runtime.CompilerThread;
+import sun.jvm.hotspot.runtime.JavaThread;
+import sun.jvm.hotspot.runtime.JavaVFrame;
+import sun.jvm.hotspot.runtime.Threads;
+import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.tools.ObjectHistogram;
+import sun.jvm.hotspot.tools.PMap;
+import sun.jvm.hotspot.tools.PStack;
 import sun.jvm.hotspot.tools.StackTrace;
 import sun.jvm.hotspot.tools.jcore.ClassDump;
 import sun.jvm.hotspot.tools.jcore.ClassFilter;
+import sun.jvm.hotspot.types.CIntegerType;
+import sun.jvm.hotspot.types.Field;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.basic.BasicType;
+import sun.jvm.hotspot.ui.classbrowser.HTMLGenerator;
+import sun.jvm.hotspot.ui.tree.CTypeTreeNodeAdapter;
+import sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter;
+import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
+import sun.jvm.hotspot.utilities.AddressOps;
+import sun.jvm.hotspot.utilities.Assert;
+import sun.jvm.hotspot.utilities.HeapProgressThunk;
+import sun.jvm.hotspot.utilities.LivenessPathElement;
+import sun.jvm.hotspot.utilities.MethodArray;
+import sun.jvm.hotspot.utilities.ObjectReader;
+import sun.jvm.hotspot.utilities.PointerFinder;
+import sun.jvm.hotspot.utilities.PointerLocation;
+import sun.jvm.hotspot.utilities.ReversePtrs;
+import sun.jvm.hotspot.utilities.ReversePtrsAnalysis;
+import sun.jvm.hotspot.utilities.RobustOopDeterminator;
+import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
+import sun.jvm.hotspot.utilities.soql.JSJavaFactory;
+import sun.jvm.hotspot.utilities.soql.JSJavaFactoryImpl;
+import sun.jvm.hotspot.utilities.soql.JSJavaScriptEngine;
 
 public class CommandProcessor {
     public abstract static class DebuggerInterface {
@@ -1132,6 +1177,10 @@
                     Klass klass = null;
                     if (t.countTokens() == 1) {
                         klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken());
+                        if (klass == null) {
+                            out.println("No such type.");
+                            return;
+                        }
                     }
                     while (base != null && base.lessThan(end)) {
                         long step = stride;
@@ -1517,7 +1566,7 @@
                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
                         thread.printThreadIDOn(new PrintStream(bos));
                         if (all || bos.toString().equals(name)) {
-                            out.println(bos.toString() + " = " + thread.getAddress());
+                            out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());
                             HTMLGenerator gen = new HTMLGenerator(false);
                             try {
                                 out.println(gen.genHTMLForJavaStackTrace(thread));
@@ -1546,7 +1595,7 @@
                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
                         thread.printThreadIDOn(new PrintStream(bos));
                         if (all || bos.toString().equals(name)) {
-                            out.println(bos.toString() + " = " + thread.getAddress());
+                            out.println("Thread " + bos.toString() + " Address " + thread.getAddress());
                             if (!all) return;
                         }
                     }
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -311,6 +311,8 @@
                 setupDebuggerLinux();
             } else if (os.equals("bsd")) {
                 setupDebuggerBsd();
+            } else if (os.equals("darwin")) {
+                setupDebuggerDarwin();
             } else {
                 // Add support for more operating systems here
                 throw new DebuggerException("Operating system " + os + " not yet supported");
@@ -370,6 +372,10 @@
                 db = new HotSpotTypeDataBase(machDesc,
                 new BsdVtblAccess(debugger, jvmLibNames),
                 debugger, jvmLibNames);
+            } else if (os.equals("darwin")) {
+                db = new HotSpotTypeDataBase(machDesc,
+                new BsdVtblAccess(debugger, jvmLibNames),
+                debugger, jvmLibNames);
             } else {
                 throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess yet)");
             }
@@ -459,6 +465,8 @@
             setupJVMLibNamesLinux();
         } else if (os.equals("bsd")) {
             setupJVMLibNamesBsd();
+        } else if (os.equals("darwin")) {
+            setupJVMLibNamesDarwin();
         } else {
             throw new RuntimeException("Unknown OS type");
         }
@@ -567,6 +575,29 @@
         jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
     }
 
+    //
+    // Darwin
+    //
+
+    private void setupDebuggerDarwin() {
+        setupJVMLibNamesDarwin();
+
+        if (cpu.equals("amd64") || cpu.equals("x86_64")) {
+            machDesc = new MachineDescriptionAMD64();
+        } else {
+            throw new DebuggerException("Darwin only supported on x86_64. Current arch: " + cpu);
+        }
+
+        BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
+        debugger = dbg;
+
+        attachDebugger();
+    }
+
+    private void setupJVMLibNamesDarwin() {
+        jvmLibNames = new String[] { "libjvm.dylib", "libjvm_g.dylib" };
+    }
+
     /** Convenience routine which should be called by per-platform
       debugger setup. Should not be called when startupMode is
       REMOTE_MODE. */
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, 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
@@ -31,6 +31,9 @@
 import sun.jvm.hotspot.debugger.x86.*;
 import sun.jvm.hotspot.debugger.cdbg.*;
 import sun.jvm.hotspot.utilities.*;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.Threads;
+import sun.jvm.hotspot.runtime.JavaThread;
 import java.lang.reflect.*;
 
 /** <P> An implementation of the JVMDebugger interface. The basic debug
@@ -51,10 +54,11 @@
 public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
     private boolean useGCC32ABI;
     private boolean attached;
-    private long    p_ps_prochandle; // native debugger handle
-    private long    symbolicator; // macosx symbolicator handle
-    private long    task; // macosx task handle
+    private long    p_ps_prochandle;      // native debugger handle
+    private long    symbolicator;         // macosx symbolicator handle
+    private long    task;                 // macosx task handle
     private boolean isCore;
+    private boolean isDarwin;             // variant for bsd
 
     // CDebugger support
     private BsdCDebugger cdbg;
@@ -208,6 +212,7 @@
             }
         }
 
+        isDarwin = getOS().equals("darwin");
         workerThread = new BsdDebuggerLocalWorkerThread(this);
         workerThread.start();
     }
@@ -240,8 +245,11 @@
 
     /* called from attach methods */
     private void findABIVersion() throws DebuggerException {
-        if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 ||
-            lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) {
+        String libjvmName = isDarwin ? "libjvm.dylib" : "libjvm.so";
+        String libjvm_gName = isDarwin? "libjvm_g.dylib" : "libjvm_g.so";
+        String javaThreadVt = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
+        if (lookupByName0(libjvmName, javaThreadVt) != 0 ||
+            lookupByName0(libjvm_gName, javaThreadVt) != 0) {
             // old C++ ABI
             useGCC32ABI = false;
         } else {
@@ -360,7 +368,8 @@
         }
 
         if (isCore) {
-            long addr = lookupByName0(objectName, symbol);
+            // MacOSX symbol with "_" as leading
+            long addr = lookupByName0(objectName, isDarwin ? "_" + symbol : symbol);
             return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
         } else {
             class LookupByNameTask implements WorkerThreadTask {
@@ -403,12 +412,12 @@
     public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
         return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
     }
+
     @Override
     public ThreadProxy getThreadForIdentifierAddress(Address addr) {
         throw new RuntimeException("unimplemented");
     }
 
-
     /** From the ThreadAccess interface via Debugger and JVMDebugger */
     public ThreadProxy getThreadForThreadId(long id) {
         return new BsdThread(this, id);
@@ -601,6 +610,33 @@
         throw new DebuggerException("Unimplemented");
     }
 
+    /** this functions used for core file reading and called from native attach0,
+        it returns an array of long integers as
+        [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
+        all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
+    public long[] getJavaThreadsInfo() {
+        requireAttach();
+        Threads threads = VM.getVM().getThreads();
+        int len = threads.getNumberOfThreads();
+        long[] result = new long[len * 3];    // triple
+        JavaThread t = threads.first();
+        long beg, end;
+        int i = 0;
+        while (t != null) {
+            end = t.getStackBaseValue();
+            beg = end - t.getStackSize();
+            BsdThread bsdt = (BsdThread)t.getThreadProxy();
+            long uid = bsdt.getUniqueThreadId();
+            if (threadList != null) threadList.add(bsdt);
+            result[i] = uid;
+            result[i + 1] = beg;
+            result[i + 2] = end;
+            t = t.next();
+            i += 3;
+        }
+        return result;
+    }
+
     static {
         System.loadLibrary("saproc");
         init0();
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -44,7 +44,8 @@
 
     BsdThread(BsdDebugger debugger, long id) {
         this.debugger = debugger;
-        this.thread_id = (int) id;
+        // use unique_thread_id to identify thread
+        this.unique_thread_id = id;
     }
 
     public boolean equals(Object obj) {
@@ -52,7 +53,7 @@
             return false;
         }
 
-        return (((BsdThread) obj).thread_id == thread_id);
+        return (((BsdThread) obj).unique_thread_id == unique_thread_id);
     }
 
     public int hashCode() {
@@ -80,4 +81,9 @@
       throws IllegalThreadStateException, DebuggerException {
         throw new DebuggerException("Unimplemented");
     }
+
+    /** this is not interface function, used in core file to get unique thread id on Macosx*/
+    public long getUniqueThreadId() {
+        return unique_thread_id;
+    }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java	Mon Apr 15 08:51:19 2013 +0200
@@ -60,8 +60,13 @@
         return null;
       }
 
+      // Check alignment of rbp
+      if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
+        return null;
+      }
+
       Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
-      if (nextRBP == null) {
+      if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) {
         return null;
       }
       Address nextPC  = rbp.getAddressAt( 1 * ADDRESS_SIZE);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java	Mon Apr 15 08:51:19 2013 +0200
@@ -61,8 +61,13 @@
         return null;
       }
 
+      // Check alignment of ebp
+      if ( dbg.getAddressValue(ebp) % ADDRESS_SIZE != 0) {
+        return null;
+      }
+
       Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE);
-      if (nextEBP == null) {
+      if (nextEBP == null || nextEBP.lessThanOrEqual(ebp)) {
         return null;
       }
       Address nextPC  = ebp.getAddressAt( 1 * ADDRESS_SIZE);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java	Mon Apr 15 08:51:19 2013 +0200
@@ -572,9 +572,14 @@
       DTFWHome = sysRoot + File.separator + ".." + File.separator +
           "Program Files" + File.separator + "Debugging Tools For Windows";
       searchList.add(DTFWHome);
-      searchList.add(DTFWHome + " (x86)");
-      searchList.add(DTFWHome + " (x64)");
 
+      // Only add the search path for the current CPU architecture:
+      String cpu = PlatformInfo.getCPU();
+      if (cpu.equals("x86")) {
+          searchList.add(DTFWHome + " (x86)");
+      } else if (cpu.equals("amd64")) {
+          searchList.add(DTFWHome + " (x64)");
+      }
       // The last place to search is the system directory:
       searchList.add(sysRoot + File.separator + "system32");
     }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -148,7 +148,7 @@
     if (doVMFields) {
       visitor.doCInt(mark, true);
       if (VM.getVM().isCompressedKlassPointersEnabled()) {
-        throw new InternalError("unimplemented");
+        visitor.doMetadata(compressedKlass, true);
       } else {
         visitor.doMetadata(klass, true);
       }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, 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
@@ -320,6 +320,10 @@
     return stackBaseField.getValue(addr);
   }
 
+  public long getStackBaseValue() {
+    return VM.getVM().getAddressValue(getStackBase());
+  }
+
   public long getStackSize() {
     return stackSizeField.getValue(addr);
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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,6 +42,7 @@
 public class Threads {
     private static JavaThreadFactory threadFactory;
     private static AddressField      threadListField;
+    private static CIntegerField     numOfThreadsField;
     private static VirtualConstructor virtualConstructor;
     private static JavaThreadPDAccess access;
 
@@ -57,6 +58,7 @@
         Type type = db.lookupType("Threads");
 
         threadListField = type.getAddressField("_thread_list");
+        numOfThreadsField = type.getCIntegerField("_number_of_threads");
 
         // Instantiate appropriate platform-specific JavaThreadFactory
         String os  = VM.getVM().getOS();
@@ -102,6 +104,10 @@
             } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
                 access = new BsdAMD64JavaThreadPDAccess();
             }
+        } else if (os.equals("darwin")) {
+            if (cpu.equals("amd64") || cpu.equals("x86_64")) {
+                access = new BsdAMD64JavaThreadPDAccess();
+            }
         }
 
         if (access == null) {
@@ -144,6 +150,10 @@
         return createJavaThreadWrapper(threadAddr);
     }
 
+    public int getNumberOfThreads() {
+        return (int) numOfThreadsField.getValue();
+    }
+
     /** Routine for instantiating appropriately-typed wrapper for a
       JavaThread. Currently needs to be public for OopUtilities to
       access it. */
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -32,6 +32,7 @@
 import sun.jvm.hotspot.debugger.cdbg.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.utilities.PlatformInfo;
 
 public class PStack extends Tool {
     // in non-verbose mode, Method*s are not printed in java frames
@@ -54,6 +55,11 @@
    }
 
    public void run(PrintStream out, Debugger dbg) {
+      if (PlatformInfo.getOS().equals("darwin")) {
+        out.println("Not available on Darwin");
+        return;
+      }
+
       CDebugger cdbg = dbg.getCDebugger();
       if (cdbg != null) {
          ConcurrentLocksPrinter concLocksPrinter = null;
--- a/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,10 +24,15 @@
 
 package sun.jvm.hotspot.types.basic;
 
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.types.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.debugger.MachineDescription;
 import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
 
 /** <P> This is a basic implementation of the TypeDataBase interface.
     It allows an external type database builder to add types to be
@@ -150,7 +155,7 @@
     return VM.getVM().getOopSize();
   }
 
-  static HashMap typeToVtbl = new HashMap();
+  HashMap typeToVtbl = new HashMap();
 
   private Address vtblForType(Type type) {
     Address vtblAddr = (Address)typeToVtbl.get(type);
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -43,8 +43,8 @@
       return "bsd";
     } else if (os.equals("OpenBSD")) {
       return "bsd";
-    } else if (os.equals("Darwin") || os.contains("OS X")) {
-      return "bsd";
+    } else if (os.contains("Darwin") || os.contains("OS X")) {
+      return "darwin";
     } else if (os.startsWith("Windows")) {
       return "win32";
     } else {
--- a/agent/src/share/native/sadis.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/agent/src/share/native/sadis.c	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -48,7 +48,10 @@
 
 #include <string.h>
 #include <dlfcn.h>
+
+#ifndef __APPLE__
 #include <link.h>
+#endif
 
 #endif
 
@@ -109,9 +112,7 @@
                                                                            jstring libname_s) {
   uintptr_t func = 0;
   const char* error_message = NULL;
-  const char* java_home;
   jboolean isCopy;
-  uintptr_t *handle = NULL;
 
   const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
   const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
@@ -167,7 +168,8 @@
                              void* event_stream,
                              int (*printf_callback)(void*, const char*, ...),
                              void* printf_stream,
-                             const char* options);
+                             const char* options,
+                             int newline);
 
 /* container for call back state when decoding instructions */
 typedef struct {
@@ -281,7 +283,7 @@
                                                          end - start,
                                                          &event_to_env,  (void*) &denv,
                                                          &printf_to_env, (void*) &denv,
-                                                         options);
+                                                         options, 0 /* newline */);
 
   /* cleanup */
   (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 
 import java.io.*;
+import java.lang.invoke.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -44,6 +45,40 @@
         private static final long serialVersionUID = -1936652569665112915L;
     }
 
+    public static final class NoFinalizableSubclass extends Assumption {
+
+        private static final long serialVersionUID = 6451169735564055081L;
+
+        private ResolvedJavaType receiverType;
+
+        public NoFinalizableSubclass(ResolvedJavaType receiverType) {
+            this.receiverType = receiverType;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + receiverType.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NoFinalizableSubclass) {
+                NoFinalizableSubclass other = (NoFinalizableSubclass) obj;
+                return other.receiverType == receiverType;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]";
+        }
+
+    }
+
     /**
      * An assumption about a unique subtype of a given type.
      */
@@ -182,6 +217,45 @@
     }
 
     /**
+     * Assumption that a call site's method handle did not change.
+     */
+    public static final class CallSiteTargetValue extends Assumption {
+
+        private static final long serialVersionUID = 1732459941784550371L;
+
+        public final CallSite callSite;
+        public final MethodHandle methodHandle;
+
+        public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) {
+            this.callSite = callSite;
+            this.methodHandle = methodHandle;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + callSite.hashCode();
+            result = prime * result + methodHandle.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof CallSiteTargetValue) {
+                CallSiteTargetValue other = (CallSiteTargetValue) obj;
+                return other.callSite == callSite && other.methodHandle == methodHandle;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]";
+        }
+    }
+
+    /**
      * Array with the assumptions. This field is directly accessed from C++ code in the
      * Graal/HotSpot implementation.
      */
@@ -233,12 +307,10 @@
      * Records an assumption that the specified type has no finalizable subclasses.
      * 
      * @param receiverType the type that is assumed to have no finalizable subclasses
-     * @return {@code true} if the assumption was recorded and can be assumed; {@code false}
-     *         otherwise
      */
-    public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
+    public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
         assert useOptimisticAssumptions;
-        return false;
+        record(new NoFinalizableSubclass(receiverType));
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Mon Apr 15 08:51:19 2013 +0200
@@ -60,13 +60,6 @@
     RegisterConfig lookupRegisterConfig();
 
     /**
-     * Custom area on the stack of each compiled method that the VM can use for its own purposes.
-     * 
-     * @return the size of the custom area in bytes
-     */
-    int getCustomStackAreaSize();
-
-    /**
      * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
      * cases, even when the compiled method has no regular call instructions.
      * 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -52,42 +52,45 @@
     }
 
     /**
-     * Represents a safepoint with associated debug info.
+     * Represents an infopoint with associated debug info. Note that safepoints are also infopoints.
      */
-    public static class Safepoint extends Site implements Comparable<Safepoint> {
+    public static class Infopoint extends Site implements Comparable<Infopoint> {
 
         private static final long serialVersionUID = 2479806696381720162L;
         public final DebugInfo debugInfo;
 
-        public Safepoint(int pcOffset, DebugInfo debugInfo) {
+        public final InfopointReason reason;
+
+        public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) {
             super(pcOffset);
             this.debugInfo = debugInfo;
+            this.reason = reason;
         }
 
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append(pcOffset);
-            sb.append("[<safepoint>]");
+            sb.append("[<infopoint>]");
             appendDebugInfo(sb, debugInfo);
             return sb.toString();
         }
 
         @Override
-        public int compareTo(Safepoint o) {
+        public int compareTo(Infopoint o) {
             if (pcOffset < o.pcOffset) {
                 return -1;
             } else if (pcOffset > o.pcOffset) {
                 return 1;
             }
-            return 0;
+            return this.reason.compareTo(o.reason);
         }
     }
 
     /**
      * Represents a call in the code.
      */
-    public static final class Call extends Safepoint {
+    public static final class Call extends Infopoint {
 
         private static final long serialVersionUID = 1440741241631046954L;
 
@@ -109,7 +112,7 @@
         public final boolean direct;
 
         public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
-            super(pcOffset, debugInfo);
+            super(pcOffset, debugInfo, InfopointReason.CALL);
             this.size = size;
             this.target = target;
             this.direct = direct;
@@ -284,7 +287,7 @@
         }
     }
 
-    private final List<Safepoint> safepoints = new ArrayList<>();
+    private final List<Infopoint> infopoints = new ArrayList<>();
     private final List<DataPatch> dataReferences = new ArrayList<>();
     private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
     private final List<Mark> marks = new ArrayList<>();
@@ -377,7 +380,7 @@
      */
     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);
+        addInfopoint(call);
     }
 
     /**
@@ -391,22 +394,22 @@
     }
 
     /**
-     * Records a safepoint in the code array.
+     * Records an infopoint in the code array.
      * 
-     * @param codePos the position of the safepoint in the code array
-     * @param debugInfo the debug info for the safepoint
+     * @param codePos the position of the infopoint in the code array
+     * @param debugInfo the debug info for the infopoint
      */
-    public void recordSafepoint(int codePos, DebugInfo debugInfo) {
-        addSafepoint(new Safepoint(codePos, debugInfo));
+    public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) {
+        addInfopoint(new Infopoint(codePos, debugInfo, reason));
     }
 
-    private void addSafepoint(Safepoint safepoint) {
-        // The safepoints list must always be sorted
-        if (!getSafepoints().isEmpty() && getSafepoints().get(getSafepoints().size() - 1).pcOffset >= safepoint.pcOffset) {
+    private void addInfopoint(Infopoint infopoint) {
+        // The infopoints list must always be sorted
+        if (!getInfopoints().isEmpty() && getInfopoints().get(getInfopoints().size() - 1).pcOffset >= infopoint.pcOffset) {
             // This re-sorting should be very rare
-            Collections.sort(getSafepoints());
+            Collections.sort(getInfopoints());
         }
-        getSafepoints().add(safepoint);
+        getInfopoints().add(infopoint);
     }
 
     /**
@@ -522,10 +525,10 @@
     }
 
     /**
-     * @return the list of safepoints, sorted by {@link Site#pcOffset}
+     * @return the list of infopoints, sorted by {@link Site#pcOffset}
      */
-    public List<Safepoint> getSafepoints() {
-        return safepoints;
+    public List<Infopoint> getInfopoints() {
+        return infopoints;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+/**
+ * A reason for infopoint insertion.
+ */
+public enum InfopointReason {
+
+    UNKNOWN, SAFEPOINT, CALL, IMPLICIT_EXCEPTION, METHOD_START, METHOD_END, LINE_NUMBER;
+
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -31,14 +31,6 @@
 public interface InstalledCode {
 
     /**
-     * Exception thrown by the runtime in case an invalidated machine code is called.
-     */
-    public abstract class MethodInvalidatedException extends RuntimeException {
-
-        private static final long serialVersionUID = -3540232440794244844L;
-    }
-
-    /**
      * Returns the method (if any) to which the installed code belongs.
      */
     ResolvedJavaMethod getMethod();
@@ -61,6 +53,12 @@
     boolean isValid();
 
     /**
+     * Invalidates this installed code such that any subsequent invocation will throw an
+     * {@link InvalidInstalledCodeException}.
+     */
+    void invalidate();
+
+    /**
      * Executes the installed code with three object arguments.
      * 
      * @param arg1 the first argument
@@ -68,7 +66,7 @@
      * @param arg3 the third argument
      * @return the value returned by the executed code
      */
-    Object execute(Object arg1, Object arg2, Object arg3);
+    Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException;
 
     /**
      * Executes the installed code with a variable number of arguments.
@@ -76,5 +74,5 @@
      * @param args the array of object arguments
      * @return the value returned by the executed code
      */
-    Object executeVarargs(Object... args);
+    Object executeVarargs(Object... args) throws InvalidInstalledCodeException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Exception thrown by the runtime in case an invalidated machine code is called.
+ */
+public final class InvalidInstalledCodeException extends Exception {
+
+    private static final long serialVersionUID = -3540232440794244844L;
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Mon Apr 15 08:51:19 2013 +0200
@@ -114,4 +114,6 @@
     long getMaxCallTargetOffset();
 
     Descriptor getDescriptor();
+
+    boolean preservesRegisters();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,10 +36,31 @@
  */
 public class TypeCheckHints {
 
-    private static final ResolvedJavaType[] NO_TYPES = {};
+    /**
+     * A receiver type profiled in a type check instruction.
+     */
+    public static class Hint {
+
+        /**
+         * A type seen while profiling a type check instruction.
+         */
+        public final ResolvedJavaType type;
+
+        /**
+         * Specifies if {@link #type} was a sub-type of the checked type.
+         */
+        public final boolean positive;
+
+        Hint(ResolvedJavaType type, boolean positive) {
+            this.type = type;
+            this.positive = positive;
+        }
+    }
+
+    private static final Hint[] NO_HINTS = {};
 
     /**
-     * If true, then {@link #types} contains the only possible type that could pass the type check
+     * If true, then {@link #hints} contains the only possible type that could pass the type check
      * because the target of the type check is a final class or has been speculated to be a final
      * class.
      */
@@ -48,63 +69,63 @@
     /**
      * The most likely types that the type check instruction will see.
      */
-    public final ResolvedJavaType[] types;
+    public final Hint[] hints;
 
     /**
      * Derives hint information for use when generating the code for a type check instruction.
      * 
-     * @param type the target type of the type check
+     * @param targetType the target type of the type check
      * @param profile the profiling information available for the instruction (if any)
      * @param assumptions the object in which speculations are recorded. This is null if
      *            speculations are not supported.
-     * @param minHintHitProbability if the probability that the type check will hit one the profiled
-     *            types (up to {@code maxHints}) is below this value, then {@link #types} will be
-     *            null
-     * @param maxHints the maximum length of {@link #types}
+     * @param minHintHitProbability if the probability that the type check will hit one of the
+     *            profiled types (up to {@code maxHints}) is below this value, then {@link #hints}
+     *            will be null
+     * @param maxHints the maximum length of {@link #hints}
      */
-    public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
-        if (type != null && canHaveSubtype(type)) {
-            types = new ResolvedJavaType[]{type};
+    public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
+        if (targetType != null && !canHaveSubtype(targetType)) {
+            hints = new Hint[]{new Hint(targetType, true)};
             exact = true;
         } else {
-            ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype();
+            ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                types = new ResolvedJavaType[]{uniqueSubtype};
+                hints = new Hint[]{new Hint(uniqueSubtype, true)};
                 if (assumptions.useOptimisticAssumptions()) {
-                    assumptions.recordConcreteSubtype(type, uniqueSubtype);
+                    assumptions.recordConcreteSubtype(targetType, uniqueSubtype);
                     exact = true;
                 } else {
                     exact = false;
                 }
             } else {
                 exact = false;
-                ResolvedJavaType[] hintTypes = NO_TYPES;
+                Hint[] hintsBuf = NO_HINTS;
                 JavaTypeProfile typeProfile = profile;
                 if (typeProfile != null) {
                     double notRecordedTypes = typeProfile.getNotRecordedProbability();
                     ProfiledType[] ptypes = typeProfile.getTypes();
                     if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
-                        hintTypes = new ResolvedJavaType[ptypes.length];
+                        hintsBuf = new Hint[ptypes.length];
                         int hintCount = 0;
                         double totalHintProbability = 0.0d;
                         for (ProfiledType ptype : ptypes) {
-                            ResolvedJavaType hint = ptype.getType();
-                            if (type != null && type.isAssignableFrom(hint)) {
-                                hintTypes[hintCount++] = hint;
+                            if (targetType != null) {
+                                ResolvedJavaType hintType = ptype.getType();
+                                hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType));
                                 totalHintProbability += ptype.getProbability();
                             }
                         }
                         if (totalHintProbability >= minHintHitProbability) {
-                            if (hintTypes.length != hintCount || hintCount > maxHints) {
-                                hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount));
+                            if (hintsBuf.length != hintCount || hintCount > maxHints) {
+                                hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount));
                             }
                         } else {
-                            hintTypes = NO_TYPES;
+                            hintsBuf = NO_HINTS;
                         }
 
                     }
                 }
-                this.types = hintTypes;
+                this.hints = hintsBuf;
             }
         }
     }
@@ -113,9 +134,9 @@
      * Determines if a given type can have subtypes other than itself. This analysis is purely
      * static; no assumptions are made.
      * 
-     * @return true if {@code type} has no subtype(s)
+     * @return true if {@code type} can have subtypes
      */
     public static boolean canHaveSubtype(ResolvedJavaType type) {
-        return isFinal(getElementalType(type).getModifiers());
+        return !isFinal(getElementalType(type).getModifiers());
     }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Mon Apr 15 08:51:19 2013 +0200
@@ -89,13 +89,19 @@
     }
 
     public static Register asIntReg(Value value) {
-        assert value.getKind() == Kind.Int;
-        return asRegister(value);
+        if (value.getKind() != Kind.Int) {
+            throw new InternalError("needed Int got: " + value.getKind());
+        } else {
+            return asRegister(value);
+        }
     }
 
     public static Register asLongReg(Value value) {
-        assert value.getKind() == Kind.Long : value.getKind();
-        return asRegister(value);
+        if (value.getKind() != Kind.Long) {
+            throw new InternalError("needed Long got: " + value.getKind());
+        } else {
+            return asRegister(value);
+        }
     }
 
     public static Register asObjectReg(Value value) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -402,7 +402,7 @@
                 if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) {
                     Method overridden = vtable.methods.put(new NameAndSignature(m), m);
                     if (overridden != null) {
-                        // System.out.println(m + " overrides " + overridden);
+                        // println(m + " overrides " + overridden);
                     }
                 }
             }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Mon Apr 15 08:51:19 2013 +0200
@@ -30,6 +30,13 @@
 public interface ConstantPool {
 
     /**
+     * Returns the number of entries the constant pool.
+     * 
+     * @return number of entries in the constant pool
+     */
+    int length();
+
+    /**
      * Ensures that the type referenced by the specified constant pool entry is loaded and
      * initialized. This can be used to compile time resolve a type. It works for field, method, or
      * type constant pool entries.
@@ -93,4 +100,14 @@
      *         entry
      */
     Object lookupConstant(int cpi);
+
+    /**
+     * Looks up the appendix at the specified index.
+     * 
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return the appendix if it exists and is resolved or {@code null}
+     */
+    Object lookupAppendix(int cpi, int opcode);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,8 @@
 
 import java.io.*;
 
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+
 /**
  * This profile object represents the type profile at a specific BCI. The precision of the supplied
  * values may vary, but a runtime that provides this information should be aware that it will be
@@ -78,6 +80,7 @@
         }
     }
 
+    private final TriState nullSeen;
     private final double notRecordedProbability;
     private final ProfiledType[] ptypes;
 
@@ -94,7 +97,8 @@
         return true;
     }
 
-    public JavaTypeProfile(double notRecordedProbability, ProfiledType... ptypes) {
+    public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType... ptypes) {
+        this.nullSeen = nullSeen;
         this.ptypes = ptypes;
         this.notRecordedProbability = notRecordedProbability;
         assert isSorted(ptypes);
@@ -111,7 +115,16 @@
     }
 
     /**
-     * A list of types for which the runtime has recorded probability information.
+     * Returns whether a null value was at the type check.
+     */
+    public TriState getNullSeen() {
+        return nullSeen;
+    }
+
+    /**
+     * A list of types for which the runtime has recorded probability information. Note that this
+     * includes both positive and negative types where a positive type is a subtype of the checked
+     * type and a negative type is not.
      */
     public ProfiledType[] getTypes() {
         return ptypes;
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Apr 15 08:51:19 2013 +0200
@@ -47,6 +47,17 @@
     }
 
     /**
+     * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types.
+     */
+    public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) {
+        ResolvedJavaType[] result = new ResolvedJavaType[types.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = types[i].resolve(accessingClass);
+        }
+        return result;
+    }
+
+    /**
      * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes.
      */
     public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) {
@@ -58,54 +69,6 @@
     }
 
     /**
-     * Gets the {@link Class} mirror for a given resolved type.
-     * 
-     * @param type the type for which the Java mirror is requested
-     * @param loader class loader from which the class must be loaded (null means use the class
-     *            loader of the {@link MetaUtil} class)
-     * @return the mirror for {@code type}
-     * @throws NoClassDefFoundError if the mirror is not available
-     */
-    public static Class getMirrorOrFail(ResolvedJavaType type, ClassLoader loader) throws NoClassDefFoundError {
-        ResolvedJavaType elementalType = getElementalType(type);
-        Class elementalClass;
-        if (elementalType.isPrimitive()) {
-            elementalClass = elementalType.getKind().toJavaClass();
-        } else {
-            try {
-                elementalClass = Class.forName(toJavaName(elementalType), true, loader);
-            } catch (ClassNotFoundException e) {
-                throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
-            }
-        }
-        if (type.isArray()) {
-            ResolvedJavaType t = type;
-            while (t.getComponentType() != null) {
-                elementalClass = Array.newInstance(elementalClass, 0).getClass();
-                t = t.getComponentType();
-            }
-        }
-        assert elementalClass != null : toJavaName(type);
-        return elementalClass;
-    }
-
-    /**
-     * Gets the {@link Class} mirror for a given resolved type.
-     * 
-     * @param type the type for which the Java mirror is requested
-     * @param loader class loader from which the class must be loaded (null means use the class
-     *            loader of the {@link MetaUtil} class)
-     * @return the mirror for {@code type} or null if it is not available
-     */
-    public static Class getMirror(ResolvedJavaType type, ClassLoader loader) {
-        try {
-            return getMirrorOrFail(type, loader);
-        } catch (NoClassDefFoundError e) {
-            return null;
-        }
-    }
-
-    /**
      * Gets the elemental type for a given type. The elemental type of an array type is the
      * corresponding zero dimensional (e.g., the elemental type of {@code int[][][]} is {@code int}
      * ). A non-array type is its own elemental type.
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Apr 15 08:51:19 2013 +0200
@@ -180,4 +180,26 @@
      * Returns the localvariable table of this method.
      */
     LocalVariableTable getLocalVariableTable();
+
+    /**
+     * Invokes the underlying method represented by this object, on the specified object with the
+     * specified parameters. This method is similar to a reflective method invocation by
+     * {@link Method#invoke}.
+     * 
+     * @param receiver The receiver for the invocation, or {@code null} if it is a static method.
+     * @param arguments The arguments for the invocation.
+     * @return The value returned by the method invocation, or {@code null} if the return type is
+     *         {@code void}.
+     */
+    Constant invoke(Constant receiver, Constant[] arguments);
+
+    /**
+     * Uses the constructor represented by this object to create and initialize a new instance of
+     * the constructor's declaring class, with the specified initialization parameters. This method
+     * is similar to a reflective instantiation by {@link Constructor#newInstance}.
+     * 
+     * @param arguments The arguments for the constructor.
+     * @return The newly created and initialized object.
+     */
+    Constant newInstance(Constant[] arguments);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -274,4 +274,22 @@
      * Returns the enclosing type of this type, if it exists, or {@code null}.
      */
     ResolvedJavaType getEnclosingType();
+
+    /**
+     * Returns an array reflecting all the constructors declared by this type. This method is
+     * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
+     */
+    ResolvedJavaMethod[] getDeclaredConstructors();
+
+    /**
+     * Returns an array reflecting all the methods declared by this type. This method is similar to
+     * {@link Class#getDeclaredMethods()} in terms of returned methods.
+     */
+    ResolvedJavaMethod[] getDeclaredMethods();
+
+    /**
+     * Creates a new array with this type as the component type and the specified length. This
+     * method is similar to {@link Array#newInstance(Class, int)}.
+     */
+    Constant newArray(int length);
 }
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Mon Apr 15 08:51:19 2013 +0200
@@ -54,4 +54,20 @@
      * is the same as the substitute method.
      */
     String signature() default "";
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     * 
+     * Not that this is still depending on whether inlining sees the correct call target, so it's
+     * only a hard guarantee for static and special invocations.
+     */
+    boolean forced() default false;
+
+    /**
+     * Determines if the substitution is for a method that may not be part of the runtime. For
+     * example, a method introduced in a later JDK version. Substitutions for such methods are
+     * omitted if the original method cannot be found.
+     */
+    boolean optional() default false;
 }
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,7 +24,7 @@
 
 import java.lang.annotation.*;
 
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.CLASS)
 @Target(ElementType.TYPE)
 public @interface ServiceProvider {
 
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,8 +26,7 @@
 
 public class PTXAssembler extends AbstractPTXAssembler {
 
-    @SuppressWarnings("unused")
-    public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) {
+    public PTXAssembler(TargetDescription target, @SuppressWarnings("unused") RegisterConfig registerConfig) {
         super(target);
     }
 
@@ -35,6 +34,18 @@
         emitString("@%p" + " " + "");
     }
 
+    public final void atq() {
+        emitString("@%q" + " " + "");
+    }
+
+    public final void add_f32(Register d, Register a, Register b) {
+        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_f64(Register d, Register a, Register b) {
+        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void add_s16(Register d, Register a, Register b) {
         emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -59,6 +70,14 @@
         emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void add_f32(Register d, Register a, float f32) {
+        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void add_f64(Register d, Register a, double f64) {
+        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void add_u16(Register d, Register a, Register b) {
         emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -123,7 +142,63 @@
         emitString("bra.uni" + " " + tgt + ";" + "");
     }
 
-    public final void div_s16(Register d, Register a, Register b) {
+    public final void cvt_s32_f32(Register d, Register a) {
+        emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_f32(Register d, Register a) {
+        emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f64_f32(Register d, Register a) {
+        emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f32_f64(Register d, Register a) {
+        emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s32_f64(Register d, Register a) {
+        emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_f64(Register d, Register a) {
+        emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f32_s32(Register d, Register a) {
+        emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f64_s32(Register d, Register a) {
+        emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s8_s32(Register d, Register a) {
+        emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_b16_s32(Register d, Register a) {
+        emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_s32(Register d, Register a) {
+        emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s32_s64(Register d, Register a) {
+        emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void div_f32(Register d, Register a, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f64(Register d, Register a, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+   public final void div_s16(Register d, Register a, Register b) {
         emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
@@ -143,10 +218,30 @@
         emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
     }
 
+    public final void div_s32(Register d, int s32, Register b) {
+        emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f32(Register d, float f32, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f64(Register d, double f64, Register b) {
+        emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
     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_f32(Register d, Register a, float f32) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void div_f64(Register d, Register a, double f64) {
+        emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void div_u16(Register d, Register a, Register b) {
         emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -255,6 +350,11 @@
         emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
 
+    public final void mov_u64(@SuppressWarnings("unused") Register d,
+                              @SuppressWarnings("unused") AbstractAddress 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() + ";" + "");
     }
@@ -319,6 +419,14 @@
         emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + "");
     }
 
+    public final void mul_f32(Register d, Register a, Register b) {
+        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_f64(Register d, Register a, Register b) {
+        emitString("smul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void mul_s16(Register d, Register a, Register b) {
         emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -343,6 +451,14 @@
         emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void mul_f32(Register d, Register a, float f32) {
+        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void mul_f64(Register d, Register a, double f64) {
+        emitString("mul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void mul_u16(Register d, Register a, Register b) {
         emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -367,6 +483,14 @@
         emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
+    public final void neg_f32(Register d, Register a) {
+        emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void neg_f64(Register d, Register a) {
+        emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
     public final void neg_s16(Register d, Register a) {
         emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -379,6 +503,42 @@
         emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
 
+    public final void not_s16(Register d, Register a) {
+        emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void not_s32(Register d, Register a) {
+        emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void not_s64(Register d, Register a) {
+        emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void or_b16(Register d, Register a, Register b) {
+        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b32(Register d, Register a, Register b) {
+        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b64(Register d, Register a, Register b) {
+        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b16(Register d, Register a, short b16) {
+        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void or_b32(Register d, Register a, int b32) {
+        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void or_b64(Register d, Register a, long b64) {
+        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
+    }
+
     public final void popc_b32(Register d, Register a) {
         emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -443,6 +603,86 @@
         emitString("ret.uni;" + " " + "");
     }
 
+    public final void setp_eq_f32(Register a, Register b) {
+        emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f32(Register a, Register b) {
+        emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f32(Register a, Register b) {
+        emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f32(Register a, Register b) {
+        emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f32(Register a, Register b) {
+        emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f32(Register a, Register b) {
+        emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_f32(float f32, Register b) {
+        emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f32(float f32, Register b) {
+        emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f32(float f32, Register b) {
+        emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f32(float f32, Register b) {
+        emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f32(float f32, Register b) {
+        emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f32(float f32, Register b) {
+        emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_f64(double f64, Register b) {
+        emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f64(double f64, Register b) {
+        emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f64(double f64, Register b) {
+        emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f64(double f64, Register b) {
+        emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f64(double f64, Register b) {
+        emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f64(double f64, Register b) {
+        emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_s64(Register a, Register b) {
+        emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_s64(long s64, Register b) {
+        emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void setp_eq_s32(Register a, Register b) {
         emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -587,6 +827,54 @@
         emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void shl_s16(Register d, Register a, Register b) {
+        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s32(Register d, Register a, Register b) {
+        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s64(Register d, Register a, Register b) {
+        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s16(Register d, Register a, int u32) {
+        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_s32(Register d, Register a, int u32) {
+        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_s64(Register d, Register a, int u32) {
+        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u16(Register d, Register a, Register b) {
+        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u32(Register d, Register a, Register b) {
+        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u64(Register d, Register a, Register b) {
+        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u16(Register d, Register a, int u32) {
+        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u32(Register d, Register a, int u32) {
+        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u64(Register d, Register a, int u32) {
+        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
     public final void shr_s16(Register d, Register a, Register b) {
         emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -631,8 +919,8 @@
         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 shr_u64(Register d, Register a, long u64) {
+        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
     public final void st_global_b8(Register a, long immOff, Register b) {
@@ -691,6 +979,14 @@
         emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
     }
 
+    public final void sub_f32(Register d, Register a, Register b) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_f64(Register d, Register a, Register b) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %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() + ";" + "");
     }
@@ -711,10 +1007,22 @@
         emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
     }
 
+    public final void sub_s64(Register d, Register a, int s32) {
+        emitString("sub.s64" + " " + "%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_f32(Register d, Register a, float f32) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void sub_f64(Register d, Register a, double f64) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void sub_s16(Register d, short s16, Register b) {
         emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + "");
     }
@@ -727,6 +1035,14 @@
         emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void sub_f32(Register d, float f32, Register b) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void sub_f64(Register d, double f64, Register b) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + "");
+    }
+
     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() + ";" + "");
     }
@@ -739,6 +1055,30 @@
         emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void xor_b16(Register d, Register a, Register b) {
+        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b32(Register d, Register a, Register b) {
+        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b64(Register d, Register a, Register b) {
+        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b16(Register d, Register a, short b16) {
+        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void xor_b32(Register d, Register a, int b32) {
+        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void xor_b64(Register d, Register a, long b64) {
+        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
+    }
+
     @Override
     public PTXAddress makeAddress(Register base, int displacement) {
         return new PTXAddress(base, displacement);
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -67,7 +67,11 @@
     protected Object runTest(String methodName, CodeGenTest test, Object... args) {
         Method method = getMethod(methodName);
         InstalledCode code = assembleMethod(method, test);
-        return code.executeVarargs(args);
+        try {
+            return code.executeVarargs(args);
+        } catch (InvalidInstalledCodeException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Mon Apr 15 08:51:19 2013 +0200
@@ -168,6 +168,16 @@
     }
 
     /**
+     * Reads a constant pool index for an invokedynamic instruction.
+     * 
+     * @return the constant pool index
+     */
+    public int readCPI4() {
+        assert opcode == Bytecodes.INVOKEDYNAMIC;
+        return Bytes.beS4(code, curBCI + 1);
+    }
+
+    /**
      * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH).
      * 
      * @return the byte
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -212,17 +212,17 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) {
         AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, canTrap ? state() : null));
+        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
         AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
-        LIRFrameState state = canTrap ? state() : null;
+        LIRFrameState state = deopting != null ? state(deopting) : null;
 
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
@@ -369,11 +369,11 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) {
         assert v.kind() == Kind.Object;
         Variable obj = newVariable(Kind.Object);
         emitMove(obj, operand(v));
-        append(new AMD64Move.NullCheckOp(obj, state()));
+        append(new AMD64Move.NullCheckOp(obj, state(deoping)));
     }
 
     @Override
@@ -509,7 +509,7 @@
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
                     if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && operand(otherDivRem) == null) {
-                        Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()));
+                        Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode);
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
@@ -526,19 +526,20 @@
         return false;
     }
 
-    private void emitDivRem(AMD64Arithmetic op, Value a, Value b) {
+    private void emitDivRem(AMD64Arithmetic op, Value a, Value b, LIRFrameState state) {
         AllocatableValue rax = AMD64.rax.asValue(a.getKind());
         emitMove(rax, a);
-        append(new DivRemOp(op, rax, asAllocatable(b), state()));
+        append(new DivRemOp(op, rax, asAllocatable(b), state));
     }
 
-    public Value[] emitIntegerDivRem(Value a, Value b) {
+    public Value[] emitIntegerDivRem(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IDIVREM, a, b);
+                emitDivRem(IDIVREM, a, b, state);
                 return new Value[]{emitMove(RAX_I), emitMove(RDX_I)};
             case Long:
-                emitDivRem(LDIVREM, a, b);
+                emitDivRem(LDIVREM, a, b, state);
                 return new Value[]{emitMove(RAX_L), emitMove(RDX_L)};
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -546,13 +547,13 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IDIV, a, b);
+                emitDivRem(IDIV, a, b, state(deopting));
                 return emitMove(RAX_I);
             case Long:
-                emitDivRem(LDIV, a, b);
+                emitDivRem(LDIV, a, b, state(deopting));
                 return emitMove(RAX_L);
             case Float: {
                 Variable result = newVariable(a.getKind());
@@ -570,21 +571,21 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b) {
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IREM, a, b);
+                emitDivRem(IREM, a, b, state(deopting));
                 return emitMove(RDX_I);
             case Long:
-                emitDivRem(LREM, a, b);
+                emitDivRem(LREM, a, b, state(deopting));
                 return emitMove(RDX_L);
             case Float: {
                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM);
-                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+                return emitCall(stub, stub.getCallingConvention(), null, a, b);
             }
             case Double: {
                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM);
-                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+                return emitCall(stub, stub.getCallingConvention(), null, a, b);
             }
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -592,13 +593,14 @@
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b) {
+    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IUDIV, a, b);
+                emitDivRem(IUDIV, a, b, state);
                 return emitMove(RAX_I);
             case Long:
-                emitDivRem(LUDIV, a, b);
+                emitDivRem(LUDIV, a, b, state);
                 return emitMove(RAX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -606,13 +608,14 @@
     }
 
     @Override
-    public Variable emitURem(Value a, Value b) {
+    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IUREM, a, b);
+                emitDivRem(IUREM, a, b, state);
                 return emitMove(RDX_I);
             case Long:
-                emitDivRem(LUREM, a, b);
+                emitDivRem(LUREM, a, b, state);
                 return emitMove(RDX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -923,4 +926,9 @@
         Value[] parameters = visitInvokeArguments(cc, node.arguments);
         append(new AMD64BreakpointOp(parameters));
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason));
+    }
 }
--- /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/ArrayTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class ArrayTest extends PTXTestBase {
+
+    @Test
+    public void testArray() {
+        compile("testArray1I");
+        compile("testArray1J");
+        compile("testArray1B");
+        compile("testArray1S");
+        compile("testArray1C");
+        compile("testArray1F");
+        compile("testArray1D");
+        compile("testArray1L");
+        compile("testStoreArray1I");
+        compile("testStoreArray1J");
+        compile("testStoreArray1B");
+        compile("testStoreArray1S");
+        compile("testStoreArray1F");
+        compile("testStoreArray1D");
+    }
+
+    public static int testArray1I(int[] array, int i) {
+        return array[i];
+    }
+
+    public static long testArray1J(long[] array, int i) {
+        return array[i];
+    }
+
+    public static byte testArray1B(byte[] array, int i) {
+        return array[i];
+    }
+
+    public static short testArray1S(short[] array, int i) {
+        return array[i];
+    }
+
+    public static char testArray1C(char[] array, int i) {
+        return array[i];
+    }
+
+    public static float testArray1F(float[] array, int i) {
+        return array[i];
+    }
+
+    public static double testArray1D(double[] array, int i) {
+        return array[i];
+    }
+
+    public static Object testArray1L(Object[] array, int i) {
+        return array[i];
+    }
+
+    public static void testStoreArray1I(int[] array, int i, int val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1B(byte[] array, int i, byte val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1S(short[] array, int i, short val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1J(long[] array, int i, long val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1F(float[] array, int i, float val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1D(double[] array, int i, double val) {
+        array[i] = val;
+    }
+
+    public static void main(String[] args) {
+        ArrayTest test = new ArrayTest();
+        for (Method m : ArrayTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,81 +22,33 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
-import java.lang.reflect.*;
-
-import org.junit.*;
+import java.lang.reflect.Method;
 
-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.PhasePosition;
-import com.oracle.graal.ptx.*;
+import org.junit.Test;
 
 /**
  * Test class for small Java methods compiled to PTX kernels.
  */
-public class BasicPTXTest extends GraalCompilerTest {
+public class BasicPTXTest extends PTXTestBase {
 
     @Test
     public void testAdd() {
-        test("testAddSnippet");
+        compile("testAddConst1I");
     }
 
-    public static int testAddSnippet(int a) {
+    public static int testAddConst1I(int a) {
         return a + 1;
     }
 
-    @Test
-    public void testArray() {
-        test("testArraySnippet");
-    }
-
-    public static int testArraySnippet(int[] array) {
-        return array[0];
-    }
-
-    private CompilationResult 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());
-        return result;
-    }
-
-    private static class PTXPhase extends Phase {
-
-        @Override
-        protected void run(StructuredGraph graph) {
-            for (LocalNode local : graph.getNodes(LocalNode.class)) {
-                if (local.kind() == Kind.Object) {
-                    local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
-                }
-            }
-        }
-
-    }
-
     public static void main(String[] args) {
-        BasicPTXTest basicPTXTest = new BasicPTXTest();
+        BasicPTXTest test = new BasicPTXTest();
         Method[] methods = BasicPTXTest.class.getMethods();
         for (Method m : methods) {
-            if (m.getAnnotation(Test.class) != null) {
-                String name = m.getName() + "Snippet";
-                System.out.println(name + ": \n" + new String(basicPTXTest.test(name).getTargetCode()));
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
             }
         }
     }
--- /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/ControlTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class ControlTest extends PTXTestBase {
+
+    @Test
+    public void testControl() {
+        compile("testSwitch1I");
+        compile("testStatic");
+        compile("testCall");
+        compile("testLookupSwitch1I");
+    }
+
+    public static int testSwitch1I(int a) {
+        switch (a) {
+        case 1:
+            return 2;
+        case 2:
+            return 3;
+        default:
+            return 4;
+        }
+    }
+
+    public static int testLookupSwitch1I(int a) {
+        switch (a) {
+        case 0:  return 1;
+        case 1:  return 2;
+        case 2:  return 3;
+        case 3:  return 1;
+        case 4:  return 2;
+        case 5:  return 3;
+        case 6:  return 1;
+        case 7:  return 2;
+        case 8:  return 3;
+        case 9:  return 1;
+        case 10: return 2;
+        case 11: return 3;
+        default: return -1;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static Object foo = null;
+
+    public static boolean testStatic(Object o) {
+        foo = o;
+        return true;
+    }
+
+    private static int method(int a, int b) {
+        return a + b;
+    }
+
+    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
+        return method(a, b);
+    }
+
+    public static void main(String[] args) {
+        ControlTest test = new ControlTest();
+        for (Method m : ControlTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /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/FloatPTXTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,245 @@
+/*
+ * 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.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.*;
+
+
+/* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */
+public class FloatPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2F");
+        compile("testAdd2D");
+        compile("testAddFConst");
+        compile("testAddConstF");
+        compile("testAddDConst");
+        compile("testAddConstD");
+    }
+
+    public static float testAdd2F(float a, float b) {
+        return a + b;
+    }
+
+    public static double testAdd2D(double a, double b) {
+        return a + b;
+    }
+
+    public static float testAddFConst(float a) {
+        return a + 32.0F;
+    }
+
+    public static float testAddConstF(float a) {
+        return 32.0F + a;
+    }
+
+    public static double testAddDConst(double a) {
+        return a + 32.0;
+    }
+
+    public static double testAddConstD(double a) {
+        return 32.0 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2F");
+        compile("testSub2D");
+        compile("testSubFConst");
+        compile("testSubConstF");
+        compile("testSubDConst");
+        compile("testSubConstD");
+    }
+
+    public static float testSub2F(float a, float b) {
+        return a - b;
+    }
+
+    public static double testSub2D(double a, double b) {
+        return a - b;
+    }
+
+    public static float testSubFConst(float a) {
+        return a - 32.0F;
+    }
+
+    public static float testSubConstF(float a) {
+        return 32.0F - a;
+    }
+
+    public static double testSubDConst(double a) {
+        return a - 32.0;
+    }
+
+    public static double testSubConstD(double a) {
+        return 32.0 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2F");
+        compile("testMul2D");
+        compile("testMulFConst");
+        compile("testMulConstF");
+        compile("testMulDConst");
+        compile("testMulConstD");
+    }
+
+    public static float testMul2F(float a, float b) {
+        return a * b;
+    }
+
+    public static double testMul2D(double a, double b) {
+        return a * b;
+    }
+
+    public static float testMulFConst(float a) {
+        return a * 32.0F;
+    }
+
+    public static float testMulConstF(float a) {
+        return 32.0F * a;
+    }
+
+    public static double testMulDConst(double a) {
+        return a * 32.0;
+    }
+
+    public static double testMulConstD(double a) {
+        return 32.0 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2F");
+        compile("testDiv2D");
+        compile("testDivFConst");
+        compile("testDivConstF");
+        compile("testDivDConst");
+        compile("testDivConstD");
+    }
+
+    public static float testDiv2F(float a, float b) {
+        return a / b;
+    }
+
+    public static double testDiv2D(double a, double b) {
+        return a / b;
+    }
+
+    public static float testDivFConst(float a) {
+        return a / 32.0F;
+    }
+
+    public static float testDivConstF(float a) {
+        return 32.0F / a;
+    }
+
+    public static double testDivDConst(double a) {
+        return a / 32.0;
+    }
+
+    public static double testDivConstD(double a) {
+        return 32.0 / a;
+    }
+
+    @Test
+    public void testNeg() {
+        compile("testNeg2F");
+        compile("testNeg2D");
+    }
+
+    public static float testNeg2F(float a) {
+        return -a;
+    }
+
+    public static double testNeg2D(double a) {
+        return -a;
+    }
+
+    @Test
+    public void testRem() {
+        // need linkage to PTX remainder()
+        // compile("testRem2F");
+        // compile("testRem2D");
+    }
+
+    public static float testRem2F(float a, float b) {
+        return a % b;
+    }
+
+    public static double testRem2D(double a, double b) {
+        return a % b;
+    }
+
+    @Test
+    public void testFloatConversion() {
+        compile("testF2I");
+        compile("testF2L");
+        compile("testF2D");
+        compile("testD2I");
+        compile("testD2L");
+        compile("testD2F");
+    }
+
+    public static int testF2I(float a) {
+        return (int) a;
+    }
+
+    public static long testF2L(float a) {
+        return (long) a;
+    }
+
+    public static double testF2D(float a) {
+        return a;
+    }
+
+    public static int testD2I(double a) {
+        return (int) a;
+    }
+
+    public static long testD2L(double a) {
+        return (long) a;
+    }
+
+    public static float testD2F(double a) {
+        return (float) a;
+    }
+
+    public static void main(String[] args) {
+        FloatPTXTest test = new FloatPTXTest();
+        for (Method m : FloatPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null &&
+                    name.startsWith("test") &&
+                    name.startsWith("testRem") == false) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /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/IntegerPTXTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,192 @@
+/*
+ * 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.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+
+public class IntegerPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2I");
+        compile("testAdd2L");
+        compile("testAdd2B");
+        compile("testAddIConst");
+        compile("testAddConstI");
+    }
+
+    public static int testAdd2I(int a, int b) {
+        return a + b;
+    }
+
+    public static long testAdd2L(long a, long b) {
+        return a + b;
+    }
+
+    public static int testAdd2B(byte a, byte b) {
+        return a + b;
+    }
+
+    public static int testAddIConst(int a) {
+        return a + 32;
+    }
+
+    public static int testAddConstI(int a) {
+        return 32 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2I");
+        compile("testSub2L");
+        compile("testSubIConst");
+        compile("testSubConstI");
+    }
+
+    public static int testSub2I(int a, int b) {
+        return a - b;
+    }
+
+    public static long testSub2L(long a, long b) {
+        return a - b;
+    }
+
+    public static int testSubIConst(int a) {
+        return a - 32;
+    }
+
+    public static int testSubConstI(int a) {
+        return 32 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2I");
+        compile("testMul2L");
+        compile("testMulIConst");
+        compile("testMulConstI");
+    }
+
+    public static int testMul2I(int a, int b) {
+        return a * b;
+    }
+
+    public static long testMul2L(long a, long b) {
+        return a * b;
+    }
+
+    public static int testMulIConst(int a) {
+        return a * 32;
+    }
+
+    public static int testMulConstI(int a) {
+        return 32 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2I");
+        compile("testDiv2L");
+        compile("testDivIConst");
+        compile("testDivConstI");
+    }
+
+    public static int testDiv2I(int a, int b) {
+        return a / b;
+    }
+
+    public static long testDiv2L(long a, long b) {
+        return a / b;
+    }
+
+    public static int testDivIConst(int a) {
+        return a / 32;
+    }
+
+    public static int testDivConstI(int a) {
+        return 32 / a;
+    }
+
+    @Test
+    public void testRem() {
+        compile("testRem2I");
+        compile("testRem2L");
+    }
+
+    public static int testRem2I(int a, int b) {
+        return a % b;
+    }
+
+    public static long testRem2L(long a, long b) {
+        return a % b;
+    }
+
+    @Test
+    public void testIntConversion() {
+        compile("testI2L");
+        compile("testL2I");
+        compile("testI2C");
+        compile("testI2B");
+        compile("testI2F");
+        compile("testI2D");
+    }
+
+    public static long testI2L(int a) {
+        return a;
+    }
+
+    public static char testI2C(int a) {
+        return (char) a;
+    }
+
+    public static byte testI2B(int a) {
+        return (byte) a;
+    }
+
+    public static float testI2F(int a) {
+        return a;
+    }
+
+    public static double testI2D(int a) {
+        return a;
+    }
+
+    public static int testL2I(long a) {
+        return (int) a;
+    }
+
+    public static void main(String[] args) {
+        IntegerPTXTest test = new IntegerPTXTest();
+        for (Method m : IntegerPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /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/LogicPTXTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+
+/* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */
+public class LogicPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAnd() {
+        compile("testAnd2I");
+        compile("testAnd2L");
+    }
+
+    public static int testAnd2I(int a, int b) {
+        return a & b;
+    }
+
+    public static long testAnd2L(long a, long b) {
+        return a & b;
+    }
+
+    @Test
+    public void testOr() {
+        compile("testOr2I");
+        compile("testOr2L");
+    }
+
+    public static int testOr2I(int a, int b) {
+        return a | b;
+    }
+
+    public static long testOr2L(long a, long b) {
+        return a | b;
+    }
+
+    @Test
+    public void testXor() {
+        compile("testXor2I");
+        compile("testXor2L");
+    }
+
+    public static int testXor2I(int a, int b) {
+        return a ^ b;
+    }
+
+    public static long testXor2L(long a, long b) {
+        return a ^ b;
+    }
+
+    @Test
+    public void testNot() {
+        compile("testNot1I");
+        compile("testNot1L");
+    }
+
+    public static int testNot1I(int a) {
+        return ~a;
+    }
+
+    public static long testNot1L(long a) {
+        return ~a;
+    }
+
+    @Test
+    public void testShiftLeft() {
+        compile("testShiftLeft2I");
+        compile("testShiftLeft2L");
+    }
+
+    public static int testShiftLeft2I(int a, int b) {
+        return a << b;
+    }
+
+    public static long testShiftLeft2L(long a, int b) {
+        return a << b;
+    }
+
+    @Test
+    public void testShiftRight() {
+        compile("testShiftRight2I");
+        compile("testShiftRight2L");
+        compile("testUnsignedShiftRight2I");
+        compile("testUnsignedShiftRight2L");
+    }
+
+    public static int testShiftRight2I(int a, int b) {
+        return a >> b;
+    }
+
+    public static long testShiftRight2L(long a, int b) {
+        return a >> b;
+    }
+
+    public static int testUnsignedShiftRight2I(int a, int b) {
+        return a >>> b;
+    }
+
+    public static long testUnsignedShiftRight2L(long a, long b) {
+        return a >>> b;
+    }
+
+    public static void main(String[] args) {
+        LogicPTXTest test = new LogicPTXTest();
+        for (Method m : LogicPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /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/PTXPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.compiler.ptx.test;
+
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.nodes.LocalNode;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.type.StampFactory;
+import com.oracle.graal.phases.Phase;
+
+
+public class PTXPhase extends Phase {
+    @Override
+    protected void run(StructuredGraph graph) {
+        /*
+         * Assume that null checks would be done on the CPU caller side prior
+         * to copying data onto the GPU.
+         */
+        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.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.compiler.ptx.test;
+
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.CompilationResult;
+import com.oracle.graal.api.code.SpeculationLog;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.runtime.Graal;
+import com.oracle.graal.compiler.GraalCompiler;
+import com.oracle.graal.compiler.ptx.PTXBackend;
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.java.GraphBuilderConfiguration;
+import com.oracle.graal.java.GraphBuilderPhase;
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.phases.OptimisticOptimizations;
+import com.oracle.graal.phases.PhasePlan;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.ptx.PTX;
+
+public abstract class PTXTestBase extends GraalCompilerTest {
+
+    protected CompilationResult compile(String test) {
+        StructuredGraph graph = parse(test);
+        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, HotSpotGraalRuntime.getInstance().getReplacements(),
+                                                               ptxBackend, target, graph.method(), graph, null, phasePlan,
+                                                               OptimisticOptimizations.NONE, new SpeculationLog());
+        return result;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Apr 15 08:51:19 2013 +0200
@@ -94,7 +94,7 @@
         codeBuffer.emitString("");
 
         // XXX For now declare one predicate and all registers
-        codeBuffer.emitString("  .reg .pred %p;");
+        codeBuffer.emitString("  .reg .pred %p,%q;");
         codeBuffer.emitString("  .reg .u32 %r<16>;");
 
         // Emit code for the LIR
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -28,35 +28,59 @@
 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.api.code.AllocatableValue;
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.DeoptimizationAction;
+import com.oracle.graal.api.code.RuntimeCallTarget;
+import com.oracle.graal.api.code.StackSlot;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.ResolvedJavaMethod;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.compiler.target.LIRGenLowerable;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.FrameMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.LIRValueUtil;
+import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.StandardOp.JumpOp;
-import com.oracle.graal.lir.ptx.*;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.ptx.PTXAddressValue;
 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.PTXBitManipulationOp;
 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp;
 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.*;
+import com.oracle.graal.nodes.calc.Condition;
+import com.oracle.graal.nodes.calc.ConvertNode;
+import com.oracle.graal.nodes.java.CompareAndSwapNode;
 
 /**
  * This class implements the PTX specific portion of the LIR generator.
  */
 public class PTXLIRGenerator extends LIRGenerator {
 
+    public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class);
+    public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class);
+
     public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
@@ -131,7 +155,7 @@
             baseRegister = asAllocatable(base);
         }
 
-        if (index != Value.ILLEGAL) {
+        if (index != Value.ILLEGAL && scale != 0) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
@@ -145,6 +169,9 @@
                 if (baseRegister == AllocatableValue.UNUSED) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
+                    Variable newBase = newVariable(Kind.Int);
+                    emitMove(newBase, baseRegister);
+                    baseRegister = newBase;
                     baseRegister = emitAdd(baseRegister, indexRegister);
                 }
             }
@@ -154,18 +181,18 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) {
         PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, canTrap ? state() : null));
+        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
         PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable input = load(inputVal);
-        append(new StoreOp(storeAddress, input, canTrap ? state() : null));
+        append(new StoreOp(storeAddress, input, deopting != null ? state(deopting) : null));
     }
 
     @Override
@@ -190,6 +217,18 @@
                 append(new CompareOp(ICMP, cond, left, right));
                 append(new BranchOp(cond, label));
                 break;
+            case Long:
+                append(new CompareOp(LCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
             case Object:
                 append(new CompareOp(ACMP, cond, left, right));
                 append(new BranchOp(cond, label));
@@ -211,7 +250,67 @@
 
     @Override
     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        throw new InternalError("NYI");
+        boolean mirrored = emitCompare(cond, left, right);
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+
+        Variable result = newVariable(trueValue.getKind());
+        switch (left.getKind().getStackKind()) {
+            case Int:
+            case Long:
+            case Object:
+                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
+                break;
+            case Float:
+            case Double:
+                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind());
+        }
+        return result;
+    }
+
+    /**
+     * This method emits the compare instruction, and may reorder the operands. It returns true if
+     * it did so.
+     * 
+     * @param a the left operand of the comparison
+     * @param b the right operand of the comparison
+     * @return true if the left and right operands were switched, false otherwise
+     */
+    private boolean emitCompare(Condition cond, Value a, Value b) {
+        Variable left;
+        Value right;
+        boolean mirrored;
+        if (LIRValueUtil.isVariable(b)) {
+            left = load(b);
+            right = loadNonConst(a);
+            mirrored = true;
+        } else {
+            left = load(a);
+            right = loadNonConst(b);
+            mirrored = false;
+        }
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, cond, left, right));
+                break;
+            case Long:
+                append(new CompareOp(LCMP, cond, left, right));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, cond, left, right));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, cond, left, right));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, cond, left, right));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return mirrored;
     }
 
     @Override
@@ -226,6 +325,12 @@
             case Int:
                 append(new Op1Stack(INEG, result, input));
                 break;
+            case Float:
+                append(new Op1Stack(FNEG, result, input));
+                break;
+            case Double:
+                append(new Op1Stack(DNEG, result, input));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -239,8 +344,17 @@
             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)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive());
         }
         return result;
     }
@@ -252,8 +366,17 @@
             case Int:
                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
         return result;
     }
@@ -265,8 +388,17 @@
             case Int:
                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
         return result;
     }
@@ -278,22 +410,50 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IREM, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LREM, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
         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) {
+    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 
@@ -304,6 +464,42 @@
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+                break;
+
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        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;
+            case Long:
+                append(new Op2Stack(LOR, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        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;
+            case Long:
+                append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -311,23 +507,35 @@
     }
 
     @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");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHL, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Variable emitShr(Value a, Value b) {
-        throw new InternalError("NYI");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHR, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
@@ -337,19 +545,91 @@
             case Int:
                 append(new ShiftOp(IUSHR, result, a, b));
                 break;
+            case Long:
+                append(new ShiftOp(LUSHR, result, a, b));
+                break;
             default:
-                GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
 
     @Override
     public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
-        throw new InternalError("NYI");
+        Variable input = load(inputVal);
+        Variable result = newVariable(opcode.to);
+        switch (opcode) {
+            case I2L:
+                append(new Unary2Op(I2L, result, input));
+                break;
+            case L2I:
+                append(new Unary1Op(L2I, result, input));
+                break;
+            case I2B:
+                append(new Unary2Op(I2B, result, input));
+                break;
+            case I2C:
+                append(new Unary1Op(I2C, result, input));
+                break;
+            case I2S:
+                append(new Unary2Op(I2S, result, input));
+                break;
+            case F2D:
+                append(new Unary2Op(F2D, result, input));
+                break;
+            case D2F:
+                append(new Unary2Op(D2F, result, input));
+                break;
+            case I2F:
+                append(new Unary2Op(I2F, result, input));
+                break;
+            case I2D:
+                append(new Unary2Op(I2D, result, input));
+                break;
+            case F2I:
+                append(new Unary2Op(F2I, result, input));
+                break;
+            case D2I:
+                append(new Unary2Op(D2I, result, input));
+                break;
+            case L2F:
+                append(new Unary2Op(L2F, result, input));
+                break;
+            case L2D:
+                append(new Unary2Op(L2D, result, input));
+                break;
+            case F2L:
+                append(new Unary2Op(F2L, result, input));
+                break;
+            case D2L:
+                append(new Unary2Op(D2L, result, input));
+                break;
+            case MOV_I2F:
+                append(new Unary2Op(MOV_I2F, result, input));
+                break;
+            case MOV_L2D:
+                append(new Unary2Op(MOV_L2D, result, input));
+                break;
+            case MOV_F2I:
+                append(new Unary2Op(MOV_F2I, result, input));
+                break;
+            case MOV_D2L:
+                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(result, input);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
@@ -434,7 +714,14 @@
 
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
+        } else {
+            assert key.getKind() == Kind.Object : key.getKind();
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+        }
     }
 
     @Override
@@ -444,7 +731,10 @@
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        Variable tmp = emitMove(key);
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
     }
 
     @Override
@@ -458,23 +748,24 @@
     }
 
     @Override
-    public void visitExceptionObject(ExceptionObjectNode i) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public void visitSafepointNode(SafepointNode i) {
+        // LIRFrameState info = state();
+        // append(new PTXSafepointOp(info, runtime().config, this));
         throw new InternalError("NYI");
     }
 
     @Override
     public void emitUnwind(Value operand) {
-        // TODO Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
         throw new InternalError("NYI");
     }
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -214,13 +214,13 @@
     }
 
     @Override
-    public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode canTrap) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) {
         // SPARC: Auto-generated method stub
 
     }
@@ -262,25 +262,25 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitRem(Value a, Value b) {
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitUDiv(Value a, Value b) {
+    public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitURem(Value a, Value b) {
+    public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
@@ -334,7 +334,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
 
     }
@@ -346,12 +346,6 @@
     }
 
     @Override
-    public void visitExceptionObject(ExceptionObjectNode i) {
-        // SPARC: Auto-generated method stub
-
-    }
-
-    @Override
     public void visitSafepointNode(SafepointNode i) {
         // SPARC: Auto-generated method stub
 
@@ -370,7 +364,13 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
         // SPARC: Auto-generated method stub
 
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,17 +22,17 @@
  */
 package com.oracle.graal.compiler.test;
 
-import java.util.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.nodes.*;
+import com.oracle.graal.virtual.phases.ea.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant
@@ -57,17 +57,25 @@
         return 1;
     }
 
-    public static Object boxedObject() {
+    public static Object boxedObjectShort() {
         return (short) 1;
     }
 
+    public static Object boxedObjectInteger() {
+        return (int) 1;
+    }
+
+    public static Integer boxedInteger() {
+        return 2;
+    }
+
     public static Short constantBoxedShort() {
         return s;
     }
 
     @Test
     public void test1() {
-        test("test1Snippet", "referenceSnippet1");
+        compareGraphs("test1Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
@@ -77,17 +85,17 @@
 
     @Test
     public void test2() {
-        test("test2Snippet", "referenceSnippet1");
+        compareGraphs("test2Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
     public static short test2Snippet() {
-        return (Short) boxedObject();
+        return (Short) boxedObjectShort();
     }
 
     @Test
     public void test3() {
-        test("test3Snippet", "referenceSnippet1");
+        compareGraphs("test3Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
@@ -101,7 +109,7 @@
 
     @Test
     public void test4() {
-        test("test4Snippet", "referenceSnippet2");
+        compareGraphs("test4Snippet", "referenceSnippet2");
     }
 
     @SuppressWarnings("all")
@@ -109,33 +117,238 @@
         return constantBoxedShort();
     }
 
-    private void test(final String snippet, final String referenceSnippet) {
-        Debug.scope("BoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() {
+    @Test
+    public void testLoop() {
+        compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true);
+    }
+
+    public static int testLoopSnippet(int n, int a) {
+        Integer sum = a;
+        for (Integer i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    public static int referenceLoopSnippet(int n, int a) {
+        int sum = a;
+        for (int i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    @Test
+    public void testLoop2() {
+        compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true);
+    }
+
+    public static int testLoop2Snippet(int n, Integer a) {
+        Integer sum = a;
+        for (Integer i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    public static int referenceLoop2Snippet(int n, Integer a) {
+        Integer sum0;
+        if (n <= 0) {
+            sum0 = a;
+        } else {
+            int sum = a;
+            for (int i = 0; i < n; i++) {
+                sum += i;
+            }
+            sum0 = sum;
+        }
+        return sum0;
+    }
+
+    public static int referenceIfSnippet(int a) {
+        int result;
+        if (a < 0) {
+            result = 2;
+        } else {
+            result = 1;
+        }
+        return result;
+    }
+
+    @Test
+    public void testIf() {
+        compareGraphs("testIfSnippet", "referenceIfSnippet");
+    }
+
+    public static int testIfSnippet(int a) {
+        Integer result;
+        if (a < 0) {
+            result = boxedInteger();
+        } else {
+            result = (Integer) boxedObjectInteger();
+        }
+        return result;
+    }
+
+    @Test
+    public void testComparison() {
+        compareGraphs("testComparison1Snippet", "referenceComparisonSnippet");
+        compareGraphs("testComparison2Snippet", "referenceComparisonSnippet");
+    }
+
+    @SuppressWarnings("cast")
+    public static boolean testComparison1Snippet(int a, int b) {
+        return ((Integer) a) == b;
+    }
+
+    public static boolean testComparison2Snippet(int a, int b) {
+        Integer x = a;
+        Integer y = b;
+        return x == y;
+    }
+
+    public static boolean referenceComparisonSnippet(int a, int b) {
+        return a == b;
+    }
+
+    @Test
+    public void testLateCanonicalization() {
+        compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet");
+    }
+
+    public static boolean testLateCanonicalizationSnippet(int a) {
+        Integer x = a;
+        Integer y = 1000;
+        return x == y;
+    }
+
+    public static boolean referenceLateCanonicalizationSnippet(int a) {
+        return a == 1000;
+    }
+
+    private StructuredGraph graph;
+
+    public static Integer materializeReferenceSnippet(int a) {
+        return Integer.valueOf(a);
+    }
+
+    public static Integer materializeTest1Snippet(int a) {
+        Integer v = a;
+
+        if (v == a) {
+            return v;
+        } else {
+            return null;
+        }
+    }
+
+    @Test
+    public void materializeTest1() {
+        test("materializeTest1Snippet", 1);
+    }
+
+    public static int intTest1Snippet() {
+        return Integer.valueOf(1);
+    }
+
+    @Test
+    public void intTest1() {
+        ValueNode result = getResult("intTest1Snippet");
+        Assert.assertTrue(result.isConstant());
+        Assert.assertEquals(1, result.asConstant().asInt());
+    }
+
+    public static int mergeTest1Snippet(boolean d, int a, int b) {
+        Integer v;
+        if (d) {
+            v = a;
+        } else {
+            v = b;
+        }
+        return v;
+    }
+
+    @Test
+    public void mergeTest1() {
+        processMethod("mergeTest1Snippet");
+    }
+
+    public static boolean equalsTest1Snippet(int x, int y) {
+        Integer a = x;
+        Integer b = y;
+        return a == b;
+    }
+
+    @Test
+    public void equalsTest1() {
+        processMethod("equalsTest1Snippet");
+    }
+
+    public static int loopTest1Snippet(int n, int v) {
+        Integer sum = 0;
+        for (int i = 0; i < n; i++) {
+            sum += v;
+        }
+        return sum;
+    }
+
+    @Test
+    public void loopTest1() {
+        processMethod("loopTest1Snippet");
+
+    }
+
+    final ValueNode getResult(String snippet) {
+        processMethod(snippet);
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first().result();
+    }
+
+    private void processMethod(final String snippet) {
+        graph = parse(snippet);
+        new ComputeProbabilityPhase().apply(graph);
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(runtime(), assumptions);
+        new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+        new CullFrameStatesPhase().apply(graph);
+    }
+
+    private void compareGraphs(final String snippet, final String referenceSnippet) {
+        compareGraphs(snippet, referenceSnippet, false, false);
+    }
+
+    private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) {
+        Debug.scope("BoxingEliminationTest " + snippet, new DebugDumpScope(snippet), new Runnable() {
 
             @Override
             public void run() {
-                StructuredGraph graph = parse(snippet);
-                BoxingMethodPool pool = new BoxingMethodPool(runtime());
-                IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase);
-                identifyBoxingPhase.apply(graph);
-                Map<Invoke, Double> hints = new HashMap<>();
-                for (Invoke invoke : graph.getInvokes()) {
-                    hints.put(invoke, 1000d);
+                graph = parse(snippet);
+
+                new ComputeProbabilityPhase().apply(graph);
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                if (loopPeeling) {
+                    new LoopTransformHighPhase().apply(graph);
+                }
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+
+                for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) {
+                    materialize.getVirtualObject().materializeAt(materialize, materialize.getValues(), false, materialize.getLockCount());
                 }
 
-                Assumptions assumptions = new Assumptions(false);
-                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(runtime(), assumptions).apply(graph);
+                new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+
                 StructuredGraph referenceGraph = parse(referenceSnippet);
-                assertEquals(referenceGraph, graph);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph);
+                new DeadCodeEliminationPhase().apply(referenceGraph);
+                new CanonicalizerPhase().apply(referenceGraph, context);
+                assertEquals(referenceGraph, graph, excludeVirtual);
             }
         });
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,7 +35,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase(runtime(), null).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
         return graph;
     }
 
@@ -53,7 +53,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(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/DegeneratedLoopsTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -81,8 +81,8 @@
 
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new InliningPhase(runtime(), null, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+                new InliningPhase(runtime(), null, replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
                 Debug.dump(graph, "Graph");
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
                 Debug.dump(referenceGraph, "ReferenceGraph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -57,7 +57,7 @@
 
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph);
+                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
                 new FloatingReadPhase().apply(graph);
 
                 ReturnNode returnNode = null;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -40,11 +40,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.test.*;
+import com.oracle.graal.hotspot.phases.WriteBarrierAdditionPhase;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -68,10 +70,12 @@
 public abstract class GraalCompilerTest extends GraalTest {
 
     protected final GraalCodeCacheProvider runtime;
+    protected final Replacements replacements;
     protected final Backend backend;
 
     public GraalCompilerTest() {
         this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
+        this.replacements = Graal.getRequiredCapability(Replacements.class);
         this.backend = Graal.getRequiredCapability(Backend.class);
     }
 
@@ -81,11 +85,15 @@
     }
 
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
-        String expectedString = getCanonicalGraphString(expected);
-        String actualString = getCanonicalGraphString(graph);
+        assertEquals(expected, graph, false);
+    }
+
+    protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) {
+        String expectedString = getCanonicalGraphString(expected, excludeVirtual);
+        String actualString = getCanonicalGraphString(graph, excludeVirtual);
         String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString;
 
-        if (expected.getNodeCount() != graph.getNodeCount()) {
+        if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) {
             Debug.dump(expected, "Node count not matching - expected");
             Debug.dump(graph, "Node count not matching - actual");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString);
@@ -98,7 +106,7 @@
     }
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
-        String graphString = getCanonicalGraphString(graph);
+        String graphString = getCanonicalGraphString(graph, false);
         Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
         ValueNode result = graph.getNodes(ReturnNode.class).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
@@ -106,7 +114,7 @@
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value);
     }
 
-    protected static String getCanonicalGraphString(StructuredGraph graph) {
+    protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual) {
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
 
@@ -125,15 +133,17 @@
             }
             result.append("\n");
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
-                int id;
-                if (canonicalId.get(node) != null) {
-                    id = canonicalId.get(node);
-                } else {
-                    id = nextId++;
-                    canonicalId.set(node, id);
+                if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) {
+                    int id;
+                    if (canonicalId.get(node) != null) {
+                        id = canonicalId.get(node);
+                    } else {
+                        id = nextId++;
+                        canonicalId.set(node, id);
+                    }
+                    String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
+                    result.append("  " + id + "|" + name + (excludeVirtual ? "\n" : "    (" + node.usages().count() + ")\n"));
                 }
-                String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
-                result.append("  " + id + "|" + name + "    (" + node.usages().count() + ")\n");
             }
         }
         return result.toString();
@@ -395,14 +405,17 @@
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
+                StructuredGraph graphCopy = graph.copy();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog());
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, 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()));
                 }
-                return addMethod(method, compResult);
+                return addMethod(method, compResult, graphCopy);
             }
         });
 
@@ -412,12 +425,12 @@
         return installedCode;
     }
 
-    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
+    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
         return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(method, compResult);
+                InstalledCode installedCode = runtime.addMethod(method, compResult, graph);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
@@ -440,25 +453,41 @@
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-        return graph;
+        return parse0(m, GraphBuilderConfiguration.getEagerDefault());
     }
 
     /**
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parseProfiled(Method m) {
+        return parse0(m, GraphBuilderConfiguration.getDefault());
+    }
+
+    /**
+     * Parses a Java method in debug mode to produce a graph with extra infopoints.
+     */
+    protected StructuredGraph parseDebug(Method m) {
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(true);
+        return parse0(m, gbConf);
+    }
+
+    private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) {
         ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
         StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
     protected PhasePlan getDefaultPhasePlan() {
+        return getDefaultPhasePlan(false);
+    }
+
+    protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) {
         PhasePlan plan = new PhasePlan();
-        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL));
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(eagerInfopointMode);
+        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, gbConf, OptimisticOptimizations.ALL));
         return plan;
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.phases.common.*;
-
-public class IfBoxingEliminationTest extends GraalCompilerTest {
-
-    private static final String REFERENCE_SNIPPET = "referenceSnippet";
-
-    public static int referenceSnippet(int a) {
-        int result;
-        if (a < 0) {
-            result = 1;
-        } else {
-            result = 2;
-        }
-        return result;
-    }
-
-    public static Integer boxedInteger() {
-        return 1;
-    }
-
-    public static Object boxedObject() {
-        return 2;
-    }
-
-    @Test
-    public void test1() {
-        test("test1Snippet");
-    }
-
-    public static int test1Snippet(int a) {
-        Integer result;
-        if (a < 0) {
-            result = boxedInteger();
-        } else {
-            result = (Integer) boxedObject();
-        }
-        return result;
-    }
-
-    private void test(final String snippet) {
-        Debug.scope("IfBoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() {
-
-            @Override
-            public void run() {
-                StructuredGraph graph = parse(snippet);
-                BoxingMethodPool pool = new BoxingMethodPool(runtime());
-                IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase);
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PhiStampPhase());
-                identifyBoxingPhase.apply(graph);
-                Map<Invoke, Double> hints = new HashMap<>();
-                for (Invoke invoke : graph.getInvokes()) {
-                    hints.put(invoke, 1000d);
-                }
-
-                Assumptions assumptions = new Assumptions(false);
-                new InliningPhase(runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new PhiStampPhase().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(runtime(), assumptions).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new DeadCodeEliminationPhase().apply(graph);
-                StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
-                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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -144,7 +144,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons.
+ */
+public class InfopointReasonTest extends GraalCompilerTest {
+
+    public static final String[] STRINGS = new String[]{"world", "everyone", "you"};
+
+    public String testMethod() {
+        StringBuilder sb = new StringBuilder("Hello ");
+        for (String s : STRINGS) {
+            sb.append(s).append(", ");
+        }
+        sb.replace(sb.length() - 2, sb.length(), "!");
+        return sb.toString();
+    }
+
+    @Test
+    public void callInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp instanceof Call) {
+                assertEquals(InfopointReason.CALL, sp.reason);
+            }
+        }
+    }
+
+    @LongTest
+    public void lineInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parseDebug(method);
+        int graphLineSPs = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.LINE_NUMBER) {
+                ++graphLineSPs;
+            }
+        }
+        assertTrue(graphLineSPs > 0);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        int lineSPs = 0;
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp.reason == InfopointReason.LINE_NUMBER) {
+                ++lineSPs;
+            }
+        }
+        assertTrue(lineSPs > 0);
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -65,8 +65,8 @@
             hints.put(invoke, 1000d);
         }
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -76,8 +76,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase.Instance(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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -133,8 +133,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -219,9 +219,9 @@
                 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 InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 }
-                new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph);
+                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
                         if (node instanceof StateSplit) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -93,8 +93,8 @@
             hints.put(invoke, 1000d);
         }
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+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.extended.*;
+import com.oracle.graal.phases.common.*;
+
+public class PushNodesThroughPiTest extends GraalCompilerTest {
+
+    public static class A {
+
+        public long x = 20;
+    }
+
+    public static class B extends A {
+
+        public long y = 10;
+    }
+
+    public static long test1Snippet(A a) {
+        B b = (B) a;
+        long ret = b.x; // this can be moved before the checkcast
+        ret += b.y;
+        // the null-check should be canonicalized with the null-check of the checkcast
+        ret += b != null ? 100 : 200;
+        return ret;
+    }
+
+    @Test
+    public void test1() {
+        final String snippet = "test1Snippet";
+        Debug.scope("PushThroughPi", new DebugDumpScope(snippet), new Runnable() {
+
+            public void run() {
+                StructuredGraph graph = compileTestSnippet(snippet);
+
+                for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
+                    Object locId = rn.location().locationIdentity();
+                    if (locId instanceof ResolvedJavaField) {
+                        ResolvedJavaField field = (ResolvedJavaField) locId;
+                        if (field.getName().equals("x")) {
+                            Assert.assertTrue(rn.object() instanceof LocalNode);
+                        } else {
+                            Assert.assertTrue(rn.object() instanceof UnsafeCastNode);
+                        }
+                    }
+                }
+
+                Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1);
+            }
+        });
+    }
+
+    private StructuredGraph compileTestSnippet(final String snippet) {
+        StructuredGraph graph = parse(snippet);
+        new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        new PushThroughPiPhase().apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java	Mon Apr 15 08:51:19 2013 +0200
@@ -85,11 +85,11 @@
             // structure changes significantly
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph);
+                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
-                new CanonicalizerPhase(runtime(), null).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
 
                 Debug.dump(graph, "After lowering");
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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(runtime(), assumptions).apply(testGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(testGraph);
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase(runtime(), assumptions).apply(refGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph);
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -166,9 +166,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -98,7 +98,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -186,13 +186,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
         assertEquals(referenceGraph, graph);
     }
 
@@ -206,19 +206,19 @@
     }
 
     public static void outputGraph(StructuredGraph graph, String message) {
-        System.out.println("========================= " + message);
+        TTY.println("========================= " + message);
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
         for (Block block : schedule.getCFG().getBlocks()) {
-            System.out.print("Block " + block + " ");
+            TTY.print("Block " + block + " ");
             if (block == schedule.getCFG().getStartBlock()) {
-                System.out.print("* ");
+                TTY.print("* ");
             }
-            System.out.print("-> ");
+            TTY.print("-> ");
             for (Block succ : block.getSuccessors()) {
-                System.out.print(succ + " ");
+                TTY.print(succ + " ");
             }
-            System.out.println();
+            TTY.println();
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
                 outputNode(node);
             }
@@ -226,11 +226,11 @@
     }
 
     private static void outputNode(Node node) {
-        System.out.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
+        TTY.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
         for (Node input : node.inputs()) {
-            System.out.print(" " + input.toString(Verbosity.Id));
+            TTY.print(" " + input.toString(Verbosity.Id));
         }
-        System.out.println(")");
+        TTY.println(")");
         if (node instanceof MergeNode) {
             for (PhiNode phi : ((MergeNode) node).phis()) {
                 outputNode(phi);
@@ -242,9 +242,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         Debug.dump(graph, "Graph");
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -115,7 +115,7 @@
 
             @Override
             public LIR call() {
-                return GraalCompiler.emitHIR(runtime, backend.target, graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
+                return GraalCompiler.emitHIR(runtime, backend.target, graph, replacements, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
             }
         });
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,13 +27,10 @@
 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.*;
 
@@ -58,7 +55,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
@@ -75,7 +72,7 @@
         try {
             Object result = compiledMethod.execute("1", "2", "3");
             Assert.assertEquals("1-2-3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -89,7 +86,7 @@
         try {
             Object result = compiledMethod.executeVarargs("1", "2", "3");
             Assert.assertEquals("1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -104,98 +101,8 @@
             f1 = "0";
             Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
             Assert.assertEquals("0 1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException 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);
-                }
-            };
-        }
-    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,7 +27,6 @@
 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.*;
@@ -59,7 +58,7 @@
         try {
             Object result = compiledMethod.executeVarargs(testString);
             Assert.assertEquals(testString, result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
 
@@ -67,7 +66,7 @@
             Object result = compiledMethod.executeVarargs(new Object[]{null});
             Assert.assertEquals(null, result);
             Assert.assertFalse(compiledMethod.isValid());
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import junit.framework.*;
+import java.util.concurrent.*;
+
 import junit.framework.Assert;
 
 import org.junit.Test;
@@ -30,10 +31,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 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.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -83,8 +87,8 @@
 
     public static int testMonitorSnippet() {
         Integer x = new Integer(0);
-        Integer[] y = new Integer[0];
-        Integer[] z = new Integer[1];
+        Double y = new Double(0);
+        Object z = new Object();
         synchronized (x) {
             synchronized (y) {
                 synchronized (z) {
@@ -106,8 +110,8 @@
      */
     public static int testMonitor2Snippet() {
         Integer x = new Integer(0);
-        Integer[] y = new Integer[0];
-        Integer[] z = new Integer[1];
+        Double y = new Double(0);
+        Object z = new Object();
         synchronized (x) {
             synchronized (y) {
                 synchronized (z) {
@@ -161,6 +165,20 @@
         return obj.x;
     }
 
+    @Test
+    public void testModifyingLoop() {
+        testEscapeAnalysis("testModifyingLoopSnippet", Constant.forInt(1), false);
+    }
+
+    public int testModifyingLoopSnippet(int a) {
+        TestObject obj = new TestObject(1, 2);
+        for (int i = 0; i < a; i++) {
+            obj.x = 3;
+            notInlineable();
+        }
+        return obj.x <= 3 ? 1 : 0;
+    }
+
     public static class TestObject2 {
 
         Object o;
@@ -192,28 +210,33 @@
         return obj2.o instanceof TestObject2;
     }
 
-    private ReturnNode testEscapeAnalysis(String snippet, Constant expectedConstantResult, boolean iterativeEscapeAnalysis) {
-        StructuredGraph graph = parse(snippet);
-        try {
-            for (Invoke n : graph.getInvokes()) {
-                n.setInliningRelevance(1);
-            }
+    private ReturnNode testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getMethod(snippet));
+        final StructuredGraph graph = new StructuredGraph(method);
+
+        return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable<ReturnNode>() {
+
+            public ReturnNode call() {
+                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+                for (Invoke n : graph.getInvokes()) {
+                    n.setInliningRelevance(1);
+                }
 
-            Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis, false).apply(graph);
-            Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
-            ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
-            if (expectedConstantResult != null) {
-                Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
-                Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context);
+                Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
+                ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
+                if (expectedConstantResult != null) {
+                    Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
+                    Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+                }
+                int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
+                Assert.assertEquals(0, newInstanceCount);
+                return returnNode;
             }
-            int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
-            Assert.assertEquals(0, newInstanceCount);
-            return returnNode;
-        } 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/ea/IterativeInliningTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class IterativeInliningTest extends GraalCompilerTest {
@@ -102,6 +103,7 @@
         graph = parse(snippet);
         new ComputeProbabilityPhase().apply(graph);
         GraalOptions.OptEarlyReadElimination = true;
-        new IterativeInliningPhase(runtime(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph);
+        HighTierContext context = new HighTierContext(runtime(), new Assumptions(false));
+        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class PEAReadEliminationTest extends GraalCompilerTest {
@@ -143,10 +144,11 @@
     }
 
     @SuppressWarnings("all")
-    public static int testBadLoopSnippet(TestObject obj, int a, int b) {
+    public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) {
         obj.x = a;
         for (int i = 0; i < 10; i++) {
             staticField = obj;
+            obj2.x = 10;
             obj.x = 0;
         }
         return obj.x;
@@ -155,6 +157,24 @@
     @Test
     public void testBadLoop() {
         ValueNode result = getReturn("testBadLoopSnippet").result();
+        assertEquals(0, graph.getNodes(LoadFieldNode.class).count());
+        assertTrue(result instanceof ProxyNode);
+        assertTrue(((ProxyNode) result).value() instanceof PhiNode);
+    }
+
+    @SuppressWarnings("all")
+    public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) {
+        obj.x = a;
+        for (int i = 0; i < 10; i++) {
+            obj.x = 0;
+            obj2.x = 10;
+        }
+        return obj.x;
+    }
+
+    @Test
+    public void testBadLoop2() {
+        ValueNode result = getReturn("testBadLoop2Snippet").result();
         assertEquals(1, graph.getNodes(LoadFieldNode.class).count());
         assertTrue(result instanceof LoadFieldNode);
     }
@@ -203,7 +223,8 @@
         graph = parse(snippet);
         new ComputeProbabilityPhase().apply(graph);
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(runtime(), assumptions, false, true).apply(graph);
+        HighTierContext context = new HighTierContext(runtime(), assumptions);
+        new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new PartialEscapeAnalysisPhase(false, true).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,18 +22,21 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import junit.framework.*;
+import java.util.concurrent.*;
+
 import junit.framework.Assert;
 
 import org.junit.Test;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -72,8 +75,8 @@
     }
 
     @SuppressWarnings("all")
-    public static Object test1Snippet(int a, int b) {
-        TestObject obj = new TestObject(1, 2);
+    public static Object test1Snippet(int a, int b, Object x, Object y) {
+        TestObject2 obj = new TestObject2(x, y);
         if (a < 0) {
             if (b < 0) {
                 return obj;
@@ -90,9 +93,9 @@
         testMaterialize("test2Snippet", 1.5, 3, LoadIndexedNode.class);
     }
 
-    public static Object test2Snippet(int a) {
-        TestObject2 obj = new TestObject2(1, 2);
-        obj.x = new TestObject2(obj, 3);
+    public static Object test2Snippet(int a, Object x, Object y, Object z) {
+        TestObject2 obj = new TestObject2(x, y);
+        obj.x = new TestObject2(obj, z);
         if (a < 0) {
             ((TestObject2) obj.x).y = null;
             obj.y = null;
@@ -125,42 +128,50 @@
     @SafeVarargs
     final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         StructuredGraph result = processMethod(snippet);
-        Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
-        Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
-        double probabilitySum = 0;
-        int materializeCount = 0;
-        for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
-            probabilitySum += materialize.probability();
-            materializeCount++;
-        }
-        Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
-        Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01);
-        for (Node node : result.getNodes()) {
-            for (Class<? extends Node> clazz : invalidNodeClasses) {
-                Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty());
+        try {
+            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
+            double probabilitySum = 0;
+            int materializeCount = 0;
+            for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
+                probabilitySum += materialize.probability();
+                materializeCount++;
             }
+            Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
+            Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01);
+            for (Node node : result.getNodes()) {
+                for (Class<? extends Node> clazz : invalidNodeClasses) {
+                    Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty());
+                }
+            }
+        } catch (AssertionError e) {
+            TypeSystemTest.outputGraph(result, snippet + ": " + e.getMessage());
+            throw e;
         }
     }
 
     private StructuredGraph processMethod(final String snippet) {
-        StructuredGraph graph = parse(snippet);
-        try {
-            new ComputeProbabilityPhase().apply(graph);
-            for (Invoke n : graph.getInvokes()) {
-                n.node().setProbability(100000);
+        return Debug.scope("PartialEscapeAnalysisTest " + snippet, new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                new ComputeProbabilityPhase().apply(graph);
+                for (Invoke n : graph.getInvokes()) {
+                    n.asNode().setProbability(100000);
+                }
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+
+                new CullFrameStatesPhase().apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                return graph;
             }
-            Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-            new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph);
-
-            new CullFrameStatesPhase().apply(graph);
-            new DeadCodeEliminationPhase().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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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 @@
 
 import static org.junit.Assert.*;
 
+import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import org.junit.*;
@@ -35,14 +36,15 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.test.*;
 
 @SuppressWarnings("unused")
 public class InliningTest extends GraalCompilerTest {
 
     @Test
     public void testInvokeStaticInlining() {
-        assertInlined(getGraph("invokeStaticSnippet"));
-        assertInlined(getGraph("invokeStaticOnInstanceSnippet"));
+        assertInlined(getGraph("invokeStaticSnippet", false));
+        assertInlined(getGraph("invokeStaticOnInstanceSnippet", false));
     }
 
     @SuppressWarnings("all")
@@ -57,9 +59,16 @@
 
     @Test
     public void testStaticBindableInlining() {
-        assertInlined(getGraph("invokeConstructorSnippet"));
-        assertInlined(getGraph("invokeFinalMethodSnippet"));
-        assertInlined(getGraph("invokeMethodOnFinalClassSnippet"));
+        assertInlined(getGraph("invokeConstructorSnippet", false));
+        assertInlined(getGraph("invokeFinalMethodSnippet", false));
+        assertInlined(getGraph("invokeMethodOnFinalClassSnippet", false));
+    }
+
+    @LongTest
+    public void testStaticBindableInliningIP() {
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalClassSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -81,14 +90,28 @@
 
     @Test
     public void testClassHierarchyAnalysis() {
-        assertInlined(getGraph("invokeLeafClassMethodSnippet"));
-        assertInlined(getGraph("invokeConcreteMethodSnippet"));
-        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet"));
-        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet"));
+        assertInlined(getGraph("invokeLeafClassMethodSnippet", false));
+        assertInlined(getGraph("invokeConcreteMethodSnippet", false));
+        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", false));
+        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", false));
+
+        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false));
+    }
 
-        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet"));
+    @LongTest
+    public void testClassHierarchyAnalysisIP() {
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", true)));
+        //@formatter:off
+        // assertInlineInfopoints(assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", true)));
+        //@formatter:on
+
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", true)));
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", true)));
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -126,19 +149,20 @@
         return superClass.protectedOverriddenMethod();
     }
 
-    private StructuredGraph getGraph(final String snippet) {
+    private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
         return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() {
-                StructuredGraph graph = parse(snippet);
-                PhasePlan phasePlan = getDefaultPhasePlan();
+                Method method = getMethod(snippet);
+                StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method);
+                PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode);
                 Assumptions assumptions = new Assumptions(true);
                 new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
-                new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
@@ -172,6 +196,35 @@
         return graph;
     }
 
+    private static int[] countMethodInfopoints(StructuredGraph graph) {
+        int start = 0;
+        int end = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.METHOD_START) {
+                ++start;
+            } else if (ipn.reason == InfopointReason.METHOD_END) {
+                ++end;
+            }
+        }
+        return new int[]{start, end};
+    }
+
+    private static StructuredGraph assertManyMethodInfopoints(StructuredGraph graph) {
+        int[] counts = countMethodInfopoints(graph);
+        if (counts[0] <= 1 || counts[1] <= 1) {
+            fail(String.format("Graph contains too few required method boundary infopoints: %d starts, %d ends.", counts[0], counts[1]));
+        }
+        return graph;
+    }
+
+    private static StructuredGraph assertFewMethodInfopoints(StructuredGraph graph) {
+        int[] counts = countMethodInfopoints(graph);
+        if (counts[0] > 1 || counts[1] > 1) {
+            fail(String.format("Graph contains too many method boundary infopoints: %d starts, %d ends.", counts[0], counts[1]));
+        }
+        return graph;
+    }
+
     // some interfaces and classes for testing
     private interface MultipleImplementorsInterface {
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Mon Apr 15 08:51:19 2013 +0200
@@ -132,9 +132,6 @@
                 }
             }
         }
-        // if (match) {
-        // System.out.println(this + " matches " + input);
-        // }
         return match;
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 15 08:51:19 2013 +0200
@@ -31,11 +31,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
@@ -43,12 +43,14 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class GraalCompiler {
 
-    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) {
+    public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Replacements replacements, 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";
 
         final CompilationResult compilationResult = new CompilationResult();
@@ -59,7 +61,7 @@
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
-                        return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog);
+                        return emitHIR(runtime, target, graph, replacements, assumptions, cache, plan, optimisticOpts, speculationLog);
                     }
                 });
                 final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
@@ -98,7 +100,7 @@
      * 
      * @param target
      */
-    public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan,
+    public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan,
                     OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
 
         if (speculationLog != null) {
@@ -117,71 +119,42 @@
         }
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
+        HighTierContext highTierContext = new HighTierContext(runtime, assumptions);
+
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
             if (GraalOptions.IterativeInlining) {
-                new IterativeInliningPhase(runtime, assumptions, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph);
+                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext);
             } else {
-                new InliningPhase(runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph);
+                new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
                     new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
                 }
             }
         }
 
-        // new ConvertUnreachedToGuardPhase(optimisticOpts).apply(graph);
-
         plan.runPhases(PhasePosition.HIGH_LEVEL, graph);
 
-        if (GraalOptions.FullUnroll) {
-            new LoopFullUnrollPhase(runtime, assumptions).apply(graph);
+        Suites.HIGH_TIER.apply(graph, highTierContext);
+
+        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
+
+        if (GraalOptions.OptPushThroughPi) {
+            new PushThroughPiPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
-            }
-        }
-
-        if (GraalOptions.OptTailDuplication) {
-            new TailDuplicationPhase().apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
             }
         }
 
-        if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) {
-            new PartialEscapeAnalysisPhase(runtime, assumptions, true, GraalOptions.OptEarlyReadElimination).apply(graph);
-        }
-
-        if (GraalOptions.OptConvertDeoptsToGuards) {
-            new ConvertDeoptimizeToGuardPhase().apply(graph);
-        }
-
-        new LockEliminationPhase().apply(graph);
-
-        if (GraalOptions.OptLoopTransform) {
-            new LoopTransformHighPhase().apply(graph);
-            new LoopTransformLowPhase().apply(graph);
-        }
-        new RemoveValueProxyPhase().apply(graph);
-
-        if (GraalOptions.CullFrameStates) {
-            new CullFrameStatesPhase().apply(graph);
-        }
-
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
-        }
-
-        new LoweringPhase(target, runtime, assumptions).apply(graph);
-
         if (GraalOptions.OptFloatingReads) {
             int mark = graph.getMark();
             new FloatingReadPhase().apply(graph);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
             if (GraalOptions.OptReadElimination) {
                 new ReadEliminationPhase().apply(graph);
             }
@@ -189,7 +162,7 @@
         new RemoveValueProxyPhase().apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
         if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
@@ -205,17 +178,23 @@
         }
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
-        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
+        // Add safepoints to loops
+        new SafepointInsertionPhase().apply(graph);
 
         new GuardLoweringPhase(target).apply(graph);
 
-        // Add safepoints to loops
-        new SafepointInsertionPhase().apply(graph);
+        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
+
+        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
+
+        new FrameStateAssignmentPhase().apply(graph);
+
+        new DeadCodeEliminationPhase().apply(graph);
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Apr 15 08:51:19 2013 +0200
@@ -82,21 +82,16 @@
                 for (Entry<VirtualObjectNode, VirtualObject> entry : virtualObjectsCopy.entrySet()) {
                     if (entry.getValue().getValues() == null) {
                         VirtualObjectNode vobj = entry.getKey();
-                        if (vobj instanceof BoxedVirtualObjectNode) {
-                            BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj;
-                            entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())});
-                        } else {
-                            Value[] values = new Value[vobj.entryCount()];
-                            if (values.length > 0) {
-                                changed = true;
-                                VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj);
-                                assert currentField != null;
-                                for (int i = 0; i < vobj.entryCount(); i++) {
-                                    values[i] = toValue(currentField.fieldValues().get(i));
-                                }
+                        Value[] values = new Value[vobj.entryCount()];
+                        if (values.length > 0) {
+                            changed = true;
+                            VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj);
+                            assert currentField != null;
+                            for (int i = 0; i < vobj.entryCount(); i++) {
+                                values[i] = toValue(currentField.fieldValues().get(i));
                             }
-                            entry.getValue().setValues(values);
                         }
+                        entry.getValue().setValues(values);
                     }
                 }
             } while (changed);
@@ -127,7 +122,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci;
+        assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
@@ -165,7 +160,7 @@
         if (value instanceof VirtualObjectNode) {
             VirtualObjectNode obj = (VirtualObjectNode) value;
             EscapeObjectState state = objectStates.get(obj);
-            if (state == null && obj.entryCount() > 0 && !(obj instanceof BoxedVirtualObjectNode)) {
+            if (state == null && obj.entryCount() > 0) {
                 // null states occur for objects with 0 fields
                 throw new GraalInternalError("no mapping found for virtual object %s", obj);
             }
@@ -173,7 +168,7 @@
                 assert !(((MaterializedObjectState) state).materializedValue() instanceof VirtualObjectNode);
                 return toValue(((MaterializedObjectState) state).materializedValue());
             } else {
-                assert obj.entryCount() == 0 || state instanceof VirtualObjectState || obj instanceof BoxedVirtualObjectNode;
+                assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
                 VirtualObject vobject = virtualObjects.get(value);
                 if (vobject == null) {
                     vobject = VirtualObject.get(obj.type(), null, virtualObjects.size());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -218,13 +218,18 @@
         return false;
     }
 
-    public LIRFrameState state() {
-        return state(null);
+    public LIRFrameState state(DeoptimizingNode deopt) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason());
     }
 
-    public LIRFrameState state(DeoptimizationReason reason) {
-        assert lastState != null || needOnlyOopMaps() : "must have state before instruction";
-        return stateFor(lastState, reason);
+    public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge);
     }
 
     public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
@@ -235,6 +240,7 @@
         if (needOnlyOopMaps()) {
             return new LIRFrameState(null, null, null, (short) -1);
         }
+        assert state != null;
         return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
     }
 
@@ -329,11 +335,10 @@
                 TTY.println("LIRGen for " + instr);
             }
             FrameState stateAfter = null;
-            if (instr instanceof StateSplit) {
+            if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) {
                 stateAfter = ((StateSplit) instr).stateAfter();
             }
             if (instr instanceof ValueNode) {
-
                 ValueNode valueNode = (ValueNode) instr;
                 if (operand(valueNode) == null) {
                     if (!peephole(valueNode)) {
@@ -594,18 +599,18 @@
     @Override
     public void emitInvoke(Invoke x) {
         AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget();
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false);
         frameMap.callsMethod(cc);
 
         Value[] parameters = visitInvokeArguments(cc, callTarget.arguments());
 
-        LIRFrameState callState = null;
-        if (x.stateAfter() != null) {
-            callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
+        LabelRef exceptionEdge = null;
+        if (x instanceof InvokeWithExceptionNode) {
+            exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
         }
+        LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
 
         Value result = cc.getReturn();
-
         if (callTarget instanceof DirectCallTargetNode) {
             emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, cc.getTemporaries(), callState);
         } else if (callTarget instanceof IndirectCallTargetNode) {
@@ -615,7 +620,7 @@
         }
 
         if (isLegal(result)) {
-            setResult(x.node(), emitMove(result));
+            setResult(x.asNode(), emitMove(result));
         }
     }
 
@@ -658,8 +663,8 @@
     }
 
     @Override
-    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) {
-        LIRFrameState info = canTrap ? state() : null;
+    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
+        LIRFrameState state = info != null ? state(info) : null;
 
         // move the arguments into the correct location
         frameMap.callsMethod(cc);
@@ -671,7 +676,7 @@
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
-        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), info);
+        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), state);
 
         if (isLegal(cc.getReturn())) {
             return emitMove(cc.getReturn());
@@ -688,25 +693,7 @@
         Value resultOperand = cc.getReturn();
         Value[] args = visitInvokeArguments(cc, x.arguments());
 
-        LIRFrameState info = null;
-        FrameState stateAfter = x.stateAfter();
-        if (stateAfter != null) {
-            // (cwimmer) I made the code that modifies the operand stack conditional. My scenario:
-            // runtime calls to, e.g.,
-            // CreateNullPointerException have no equivalent in the bytecodes, so there is no invoke
-            // bytecode.
-            // Therefore, the result of the runtime call was never pushed to the stack, and we
-            // cannot pop it here.
-            FrameState stateBeforeReturn = stateAfter;
-            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, null);
-        } else {
-            info = state();
-        }
-
-        emitCall(call, resultOperand, args, cc.getTemporaries(), info);
+        emitCall(call, resultOperand, args, cc.getTemporaries(), state(x));
 
         if (isLegal(resultOperand)) {
             setResult(x, emitMove(resultOperand));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/Suites.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.phases;
+
+import java.util.*;
+
+import com.oracle.graal.loop.phases.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.phases.ea.*;
+
+public class Suites {
+
+    public static final PhaseSuite<HighTierContext> HIGH_TIER = createHighTier();
+
+    private static PhaseSuite<HighTierContext> createHighTier() {
+        ArrayList<BasePhase<? super HighTierContext>> phases = new ArrayList<>();
+
+        if (GraalOptions.FullUnroll) {
+            phases.add(new LoopFullUnrollPhase());
+            if (GraalOptions.OptCanonicalizer) {
+                phases.add(new CanonicalizerPhase());
+            }
+        }
+
+        if (GraalOptions.OptTailDuplication) {
+            phases.add(new TailDuplicationPhase());
+            if (GraalOptions.OptCanonicalizer) {
+                phases.add(new CanonicalizerPhase());
+            }
+        }
+
+        if (GraalOptions.PartialEscapeAnalysis) {
+            phases.add(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination));
+        }
+
+        if (GraalOptions.OptConvertDeoptsToGuards) {
+            phases.add(new ConvertDeoptimizeToGuardPhase());
+        }
+
+        phases.add(new LockEliminationPhase());
+
+        if (GraalOptions.OptLoopTransform) {
+            phases.add(new LoopTransformHighPhase());
+            phases.add(new LoopTransformLowPhase());
+        }
+        phases.add(new RemoveValueProxyPhase());
+
+        if (GraalOptions.CullFrameStates) {
+            phases.add(new CullFrameStatesPhase());
+        }
+
+        if (GraalOptions.OptCanonicalizer) {
+            phases.add(new CanonicalizerPhase());
+        }
+
+        return new PhaseSuite<>("HighTier", phases);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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.debug.test;
+
+import java.io.*;
+
+import org.junit.*;
+
+import com.oracle.graal.debug.*;
+
+public class DebugHistogramTest {
+
+    @Test
+    public void testEmptyHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.print(new PrintStream(outputStream));
+        Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString());
+    }
+
+    @Test
+    public void testSingleEntryHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add(new Integer(1));
+        histogram.add(new Integer(1));
+        histogram.print(new PrintStream(outputStream));
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[1]);
+        Assert.assertEquals(
+                        "| 1                                                  | 2          | ==================================================================================================== |",
+                        lines[2]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[3]);
+    }
+
+    @Test
+    public void testMultipleEntryHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add(new Integer(1));
+        histogram.add(new Integer(2));
+        histogram.add(new Integer(2));
+        histogram.print(new PrintStream(outputStream));
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[1]);
+        Assert.assertEquals(
+                        "| 2                                                  | 2          | ==================================================================================================== |",
+                        lines[2]);
+        Assert.assertEquals(
+                        "| 1                                                  | 1          | ==================================================                                                   |",
+                        lines[3]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[4]);
+    }
+
+    @Test
+    public void testTooLongValueString() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add("MyCustomValue");
+        histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10);
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]);
+        Assert.assertEquals("----------------------------------------", lines[1]);
+        Assert.assertEquals("| MyCusto... | 1          | ========== |", lines[2]);
+        Assert.assertEquals("----------------------------------------", lines[3]);
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Apr 15 08:51:19 2013 +0200
@@ -189,6 +189,10 @@
         }
     }
 
+    public static DebugHistogram createHistogram(String name) {
+        return new DebugHistogramImpl(name);
+    }
+
     public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled,
                     final Collection<DebugDumpHandler> dumpHandlers, final PrintStream output) {
         return new DebugConfig() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.debug;
+
+import java.io.*;
+
+public interface DebugHistogram {
+
+    String getName();
+
+    void add(Object value);
+
+    void print(PrintStream os);
+
+    void print(PrintStream os, int limit, int nameSize, int barSize);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,110 @@
+/*
+ * 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+
+public class DebugHistogramImpl implements DebugHistogram {
+
+    public static final int NumberSize = 10;
+    public static final int DefaultNameSize = 50;
+    public static final int DefaultBarSize = 100;
+    private final String name;
+    private HashMap<Object, Integer> map = new HashMap<>();
+
+    public DebugHistogramImpl(String name) {
+        this.name = name;
+    }
+
+    public void add(Object value) {
+        if (!map.containsKey(value)) {
+            map.put(value, 1);
+        } else {
+            map.put(value, map.get(value) + 1);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void print(PrintStream os) {
+        print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
+    }
+
+    public void print(PrintStream os, int limit, int nameSize, int barSize) {
+
+        List<Object> list = new ArrayList<>(map.keySet());
+        if (list.size() == 0) {
+            // No elements in the histogram.
+            os.printf("%s is empty.\n", name);
+            return;
+        }
+
+        // Sort from highest to smallest.
+        Collections.sort(list, new Comparator<Object>() {
+
+            @Override
+            public int compare(Object o1, Object o2) {
+                return map.get(o2) - map.get(o1);
+            }
+        });
+
+        // Sum up the total number of elements.
+        int total = 0;
+        for (Object o : list) {
+            total += map.get(o);
+        }
+
+        // Print header.
+        os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total);
+
+        int max = map.get(list.get(0));
+        final int lineSize = nameSize + NumberSize + barSize + 10;
+        printLine(os, '-', lineSize);
+        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            Object o = list.get(i);
+            int value = map.get(o);
+            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
+            Arrays.fill(bar, '=');
+            String objectString = o.toString();
+            if (objectString.length() > nameSize) {
+                objectString = objectString.substring(0, nameSize - 3) + "...";
+            }
+            os.printf(formatString, objectString, value, new String(bar));
+        }
+        printLine(os, '-', lineSize);
+    }
+
+    private static void printLine(PrintStream printStream, char c, int lineSize) {
+        char[] charArr = new char[lineSize];
+        Arrays.fill(charArr, c);
+        printStream.printf("%s\n", new String(charArr));
+    }
+}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +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.graph;
-
-public interface TestNodeInterface {
-
-    String getName();
-}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +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.graph;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-public class TypedNodeIteratorTest {
-
-    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
-
-        private final String name;
-
-        public TestNode(String name) {
-            this.name = name;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    @Test
-    public void singleNodeTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        assertTrue(graph.hasNode(TestNode.class));
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void deletingNodeTest() {
-        TestNode testNode = new TestNode("a");
-        Graph graph = new Graph();
-        graph.add(testNode);
-        testNode.safeDelete();
-        assertEquals("", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void deleteAndAddTest() {
-        TestNode testNode = new TestNode("b");
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        graph.add(testNode);
-        testNode.safeDelete();
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
-        graph.add(new TestNode("c"));
-        assertEquals("ac", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void iteratorBehaviorTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        Iterator<TestNode> iterator = graph.getNodes(TestNode.class).iterator();
-        assertTrue(iterator.hasNext());
-        assertEquals("a", iterator.next().getName());
-        assertFalse(iterator.hasNext());
-        graph.add(new TestNode("b"));
-        assertTrue(iterator.hasNext());
-        assertEquals("b", iterator.next().getName());
-        assertFalse(iterator.hasNext());
-        TestNode c = new TestNode("c");
-        graph.add(c);
-        assertTrue(iterator.hasNext());
-        c.safeDelete();
-        assertFalse(iterator.hasNext());
-    }
-
-    @Test
-    public void complicatedIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            String name = tn.getName();
-            for (int i = 0; i < name.length(); ++i) {
-                char c = name.charAt(i);
-                if (c == 'a') {
-                    tn.safeDelete();
-                    graph.add(new TestNode("b"));
-                    graph.add(new TestNode("c"));
-                } else if (c == 'b') {
-                    tn.safeDelete();
-                } else if (c == 'c') {
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                } else if (c == 'd') {
-                    for (TestNode tn2 : graph.getNodes(TestNode.class)) {
-                        if (tn2.getName().equals("e")) {
-                            tn2.safeDelete();
-                        } else if (tn2.getName().equals("c")) {
-                            tn2.safeDelete();
-                        }
-                    }
-                } else if (c == 'e') {
-                    fail("All e nodes must have been deleted by visiting the d node");
-                }
-            }
-        }
-        assertEquals("dddd", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void addingNodeDuringIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        StringBuilder sb = new StringBuilder();
-        int z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            if (z == 0) {
-                graph.add(new TestNode("b"));
-            }
-            sb.append(tn.getName());
-            z++;
-        }
-        assertEquals(2, z);
-        assertEquals("ab", sb.toString());
-        z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            if (z == 0) {
-                graph.add(new TestNode("c"));
-            }
-            assertNotNull(tn);
-            z++;
-        }
-        assertEquals(3, z);
-    }
-
-    public static String toString(Iterable<? extends TestNodeInterface> nodes) {
-        StringBuilder sb = new StringBuilder();
-        for (TestNodeInterface tn : nodes) {
-            sb.append(tn.getName());
-        }
-        return sb.toString();
-    }
-}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * 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.graph;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-public class TypedNodeIteratorTest2 {
-
-    private static class NodeA extends Node implements TestNodeInterface {
-
-        private final String name;
-
-        public NodeA(String name) {
-            this.name = name;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    private static class NodeB extends NodeA implements Node.IterableNodeType {
-
-        public NodeB(String name) {
-            super(name);
-        }
-    }
-
-    private static class NodeC extends NodeB {
-
-        public NodeC(String name) {
-            super(name);
-        }
-    }
-
-    private static class NodeD extends NodeC {
-
-        public NodeD(String name) {
-            super(name);
-        }
-    }
-
-    @Test
-    public void simpleSubclassTest() {
-        Graph graph = new Graph();
-        graph.add(new NodeB("b"));
-        graph.add(new NodeD("d"));
-
-        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
-        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
-    }
-
-    @Test
-    public void addingNodeDuringIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new NodeB("b1"));
-        NodeD d1 = graph.add(new NodeD("d1"));
-        StringBuilder sb = new StringBuilder();
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
-            if (tn == d1) {
-                graph.add(new NodeB("b2"));
-            }
-            sb.append(tn.getName());
-        }
-        assertEquals("b1d1b2", sb.toString());
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
-            if (tn == d1) {
-                graph.add(new NodeB("b3"));
-            }
-            assertNotNull(tn);
-        }
-        assertEquals(4, graph.getNodes(NodeB.class).count());
-        assertEquals(1, graph.getNodes(NodeD.class).count());
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TestNodeInterface.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,28 @@
+/*
+ * 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.graph.test;
+
+public interface TestNodeInterface {
+
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.graph.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class TypedNodeIteratorTest {
+
+    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
+
+        private final String name;
+
+        public TestNode(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    @Test
+    public void singleNodeTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        assertTrue(graph.hasNode(TestNode.class));
+        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void deletingNodeTest() {
+        TestNode testNode = new TestNode("a");
+        Graph graph = new Graph();
+        graph.add(testNode);
+        testNode.safeDelete();
+        assertEquals("", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void deleteAndAddTest() {
+        TestNode testNode = new TestNode("b");
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        graph.add(testNode);
+        testNode.safeDelete();
+        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+        graph.add(new TestNode("c"));
+        assertEquals("ac", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void iteratorBehaviorTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        Iterator<TestNode> iterator = graph.getNodes(TestNode.class).iterator();
+        assertTrue(iterator.hasNext());
+        assertEquals("a", iterator.next().getName());
+        assertFalse(iterator.hasNext());
+        graph.add(new TestNode("b"));
+        assertTrue(iterator.hasNext());
+        assertEquals("b", iterator.next().getName());
+        assertFalse(iterator.hasNext());
+        TestNode c = new TestNode("c");
+        graph.add(c);
+        assertTrue(iterator.hasNext());
+        c.safeDelete();
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void complicatedIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            String name = tn.getName();
+            for (int i = 0; i < name.length(); ++i) {
+                char c = name.charAt(i);
+                if (c == 'a') {
+                    tn.safeDelete();
+                    graph.add(new TestNode("b"));
+                    graph.add(new TestNode("c"));
+                } else if (c == 'b') {
+                    tn.safeDelete();
+                } else if (c == 'c') {
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                } else if (c == 'd') {
+                    for (TestNode tn2 : graph.getNodes(TestNode.class)) {
+                        if (tn2.getName().equals("e")) {
+                            tn2.safeDelete();
+                        } else if (tn2.getName().equals("c")) {
+                            tn2.safeDelete();
+                        }
+                    }
+                } else if (c == 'e') {
+                    fail("All e nodes must have been deleted by visiting the d node");
+                }
+            }
+        }
+        assertEquals("dddd", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void addingNodeDuringIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        StringBuilder sb = new StringBuilder();
+        int z = 0;
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            if (z == 0) {
+                graph.add(new TestNode("b"));
+            }
+            sb.append(tn.getName());
+            z++;
+        }
+        assertEquals(2, z);
+        assertEquals("ab", sb.toString());
+        z = 0;
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            if (z == 0) {
+                graph.add(new TestNode("c"));
+            }
+            assertNotNull(tn);
+            z++;
+        }
+        assertEquals(3, z);
+    }
+
+    public static String toString(Iterable<? extends TestNodeInterface> nodes) {
+        StringBuilder sb = new StringBuilder();
+        for (TestNodeInterface tn : nodes) {
+            sb.append(tn.getName());
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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.graph.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class TypedNodeIteratorTest2 {
+
+    private static class NodeA extends Node implements TestNodeInterface {
+
+        private final String name;
+
+        public NodeA(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    private static class NodeB extends NodeA implements Node.IterableNodeType {
+
+        public NodeB(String name) {
+            super(name);
+        }
+    }
+
+    private static class NodeC extends NodeB {
+
+        public NodeC(String name) {
+            super(name);
+        }
+    }
+
+    private static class NodeD extends NodeC {
+
+        public NodeD(String name) {
+            super(name);
+        }
+    }
+
+    @Test
+    public void simpleSubclassTest() {
+        Graph graph = new Graph();
+        graph.add(new NodeB("b"));
+        graph.add(new NodeD("d"));
+
+        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
+        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
+    }
+
+    @Test
+    public void addingNodeDuringIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new NodeB("b1"));
+        NodeD d1 = graph.add(new NodeD("d1"));
+        StringBuilder sb = new StringBuilder();
+        for (NodeB tn : graph.getNodes(NodeB.class)) {
+            if (tn == d1) {
+                graph.add(new NodeB("b2"));
+            }
+            sb.append(tn.getName());
+        }
+        assertEquals("b1d1b2", sb.toString());
+        for (NodeB tn : graph.getNodes(NodeB.class)) {
+            if (tn == d1) {
+                graph.add(new NodeB("b3"));
+            }
+            assertNotNull(tn);
+        }
+        assertEquals(4, graph.getNodes(NodeB.class).count());
+        assertEquals(1, graph.getNodes(NodeD.class).count());
+    }
+
+}
--- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Mon Apr 15 08:51:19 2013 +0200
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
 
-<!--
-    This configuration file was written by the eclipse-cs plugin configuration editor
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
 -->
-<!--
-    Checkstyle-Configuration: Maxine Checks
-    Description: none
+<!--
+    Checkstyle-Configuration: Maxine Checks
+    Description: none
 -->
 <module name="Checker">
-  <property name="severity" value="warning"/>
+  <property name="severity" value="error"/>
   <module name="TreeWalker">
     <property name="tabWidth" value="4"/>
     <module name="FileContentsHolder"/>
@@ -197,4 +197,14 @@
     <property name="format" value="\r\n"/>
     <property name="message" value="illegal Windows line ending"/>
   </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop system..print check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume system..print check"/>
+    <property name="checkFormat" value="RegexpSingleline"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
+  </module>
+  <module name="RegexpSingleline">
+    <property name="format" value="System\.(out|err)\.print"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
 </module>
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.graph;
 
+import java.io.*;
+
 public abstract class GraphEvent {
 
     private Exception exceptionContext;
@@ -43,9 +45,9 @@
         }
 
         @Override
-        public StackTraceElement[] print(StackTraceElement[] last) {
-            System.out.println(type.toString() + ", " + nodeString);
-            return super.print(last);
+        public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
+            stream.println(type.toString() + ", " + nodeString);
+            return super.print(last, stream);
         }
     }
 
@@ -72,7 +74,7 @@
         exceptionContext = new Exception();
     }
 
-    public StackTraceElement[] print(StackTraceElement[] last) {
+    public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
         StackTraceElement[] stackTrace = exceptionContext.getStackTrace();
 
         boolean atTop = true;
@@ -90,7 +92,7 @@
                     continue;
                 }
             }
-            System.out.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber()));
+            stream.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber()));
         }
         return stackTrace;
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.graph;
 
+import java.io.*;
 import java.util.*;
 
 public class GraphEventLog {
@@ -32,10 +33,10 @@
         this.events.add(e);
     }
 
-    public void printEvents() {
+    public void printEvents(PrintStream stream) {
         StackTraceElement[] last = new StackTraceElement[0];
         for (GraphEvent e : events) {
-            last = e.print(last);
+            last = e.print(last, stream);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
 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.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
@@ -42,13 +42,13 @@
 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.StandardOp.ParametersOp;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64Move.*;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
@@ -161,20 +161,10 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = state();
+        LIRFrameState info = state(i);
         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) {
@@ -242,8 +232,8 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
-        append(new AMD64DeoptimizeOp(action, reason, state()));
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+        append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,23 +37,22 @@
 import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
+import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
+import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
 import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.DecryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.EncryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
-import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
-import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
 
+import com.oracle.graal.amd64.*;
 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.replacements.amd64.*;
-import com.oracle.graal.replacements.*;
 
 public class AMD64HotSpotRuntime extends HotSpotRuntime {
 
@@ -73,13 +72,13 @@
                 /*             ret */ ret(Kind.Void));
 
         addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub,
-                /*           temps */ null,
+                /*           temps */ new Register[]{AMD64.rax},
                 /*             ret */ ret(Kind.Float),
                 /* arg0:         a */ javaCallingConvention(Kind.Float,
                 /* arg1:         b */                       Kind.Float));
 
         addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub,
-                /*           temps */ null,
+                /*           temps */ new Register[]{AMD64.rax},
                 /*             ret */ ret(Kind.Double),
                 /* arg0:         a */ javaCallingConvention(Kind.Double,
                 /* arg1:         b */                       Kind.Double));
@@ -208,10 +207,9 @@
     private AMD64ConvertSnippets.Templates convertSnippets;
 
     @Override
-    public void installReplacements(Backend backend, ReplacementsInstaller installer, Assumptions assumptions) {
-        installer.installSnippets(AMD64ConvertSnippets.class);
-        convertSnippets = new AMD64ConvertSnippets.Templates(this, assumptions, graalRuntime.getTarget());
-        super.installReplacements(backend, installer, assumptions);
+    public void registerReplacements(Replacements replacements) {
+        convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        super.registerReplacements(replacements);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Mon Apr 15 08:51:19 2013 +0200
@@ -52,7 +52,7 @@
 
     @Use({REG}) protected Value metaspaceMethod;
 
-    AMD64IndirectCallOp(InvokeTarget targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
+    AMD64IndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
         super(targetMethod, result, parameters, temps, targetAddress, state);
         this.metaspaceMethod = metaspaceMethod;
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Mon Apr 15 08:51:19 2013 +0200
@@ -63,11 +63,11 @@
         if (config.isPollingPageFar) {
             asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
             tasm.recordMark(Marks.MARK_POLL_FAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister()));
         } else {
             tasm.recordMark(Marks.MARK_POLL_NEAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             // 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.getRegister(), new AMD64Address(rip, offset));
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java	Mon Apr 15 08:51:19 2013 +0200
@@ -38,6 +38,7 @@
  */
 public class InvocationSocket {
 
+    // CheckStyle: stop system..print check
     private static final boolean DEBUG = false;
     private static final boolean COUNT_CALLS = false;
 
@@ -279,4 +280,5 @@
         output.writeObject(new Result(obj));
         output.flush();
     }
+    // CheckStyle: resume system..print check
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +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;
-
-import static org.junit.Assert.*;
-
-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.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}.
- */
-public class ArrayCopyIntrinsificationTest extends GraalCompilerTest {
-
-    @Override
-    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
-        int nodeCount = graph.getNodeCount();
-        InstalledCode result = super.getCode(method, graph);
-        boolean graphWasProcessed = nodeCount != graph.getNodeCount();
-        if (graphWasProcessed) {
-            if (mustIntrinsify) {
-                for (Node node : graph.getNodes()) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
-                        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()));
-                    }
-                }
-            } else {
-                boolean found = false;
-                for (Node node : graph.getNodes()) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
-                        JavaMethod callee = directCall.target();
-                        if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
-                            found = true;
-                        } else {
-                            fail("found invoke to some method other than arraycopy: " + callee);
-                        }
-                    }
-                }
-                Assert.assertTrue("did not find invoke to arraycopy", found);
-            }
-        }
-        return result;
-    }
-
-    boolean mustIntrinsify = true;
-
-    @Test
-    public void test0() {
-        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
-        // Array store checks
-        test("genericArraycopy", new Object(), 0, new Object[0], 0, 0);
-        test("genericArraycopy", new Object[0], 0, new Object(), 0, 0);
-
-        mustIntrinsify = true;
-    }
-
-    @Test
-    public void test1() {
-        String name = "intArraycopy";
-        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        // Null checks
-        test(name, null, 0, src, 0, 0);
-        test(name, src, 0, null, 0, 0);
-        // Bounds checks
-        test(name, src, 0, src, 0, -1);
-        test(name, src, 0, src, 0, src.length + 1);
-    }
-
-    @Test
-    public void testByte() {
-        byte[] src = {-1, 0, 1, 2, 3, 4};
-        testHelper("byteArraycopy", src);
-    }
-
-    @Test
-    public void testChar() {
-        char[] src = "some string of chars".toCharArray();
-        testHelper("charArraycopy", src);
-    }
-
-    @Test
-    public void testShort() {
-        short[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("shortArraycopy", src);
-    }
-
-    @Test
-    public void testInt() {
-        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("intArraycopy", src);
-    }
-
-    @Test
-    public void testFloat() {
-        float[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("floatArraycopy", src);
-    }
-
-    @Test
-    public void testLong() {
-        long[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("longArraycopy", src);
-    }
-
-    @Test
-    public void testDouble() {
-        double[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("doubleArraycopy", src);
-    }
-
-    @Test
-    public void testObject() {
-        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
-
-        Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()};
-        testHelper("objectArraycopy", src);
-
-        mustIntrinsify = true;
-    }
-
-    @Test
-    public void testObjectExact() {
-        Integer[] src = {1, 2, 3, 4};
-        testHelper("objectArraycopyExact", src);
-    }
-
-    private static Object newArray(Object proto, int length) {
-        assert proto != null;
-        assert proto.getClass().isArray();
-        return Array.newInstance(proto.getClass().getComponentType(), length);
-    }
-
-    private void testHelper(String name, Object src) {
-        int srcLength = Array.getLength(src);
-
-        // Complete array copy
-        test(name, src, 0, newArray(src, srcLength), 0, srcLength);
-
-        for (int length : new int[]{0, 1, srcLength - 1, srcLength}) {
-            // Partial array copying
-            test(name, src, 0, newArray(src, length), 0, length);
-            test(name, src, srcLength - length, newArray(src, length), 0, length);
-            test(name, src, 0, newArray(src, srcLength), 0, length);
-        }
-    }
-
-    public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/HotSpotMethodSubstitutionTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +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;
-
-import org.junit.*;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.replacements.*;
-
-/**
- * Tests HotSpot specific {@link MethodSubstitution}s.
- */
-public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest {
-
-    @Test
-    public void testObjectSubstitutions() {
-        test("getClass_");
-        test("objectHashCode");
-
-        Object obj = new Object();
-
-        assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string"));
-        assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj));
-    }
-
-    @SuppressWarnings("all")
-    public static boolean getClass_(Object obj, Class<?> clazz) {
-        return obj.getClass() == clazz;
-    }
-
-    @SuppressWarnings("all")
-    public static int objectHashCode(TestClassA obj) {
-        return obj.hashCode();
-    }
-
-    @Test
-    public void testClassSubstitutions() {
-        test("getModifiers");
-        test("isInstance");
-        test("isInterface");
-        test("isArray");
-        test("isPrimitive");
-        test("getSuperClass");
-        test("getComponentType");
-
-        for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
-            assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
-            assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
-            assertEquals(c.isArray(), ClassSubstitutions.isArray(c));
-            assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c));
-            assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c));
-            assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c));
-            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-                assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
-            }
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static int getModifiers(Class<?> clazz) {
-        return clazz.getModifiers();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isInstance(Class<?> clazz) {
-        return clazz.isInstance(Number.class);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isInterface(Class<?> clazz) {
-        return clazz.isInterface();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isArray(Class<?> clazz) {
-        return clazz.isArray();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isPrimitive(Class<?> clazz) {
-        return clazz.isPrimitive();
-    }
-
-    @SuppressWarnings("all")
-    public static Class<?> getSuperClass(Class<?> clazz) {
-        return clazz.getSuperclass();
-    }
-
-    @SuppressWarnings("all")
-    public static Class<?> getComponentType(Class<?> clazz) {
-        return clazz.getComponentType();
-    }
-
-    @Test
-    public void testThreadSubstitutions() {
-        test("currentThread");
-        test("threadIsInterrupted");
-        test("threadInterrupted");
-
-        Thread currentThread = Thread.currentThread();
-        assertEquals(currentThread, ThreadSubstitutions.currentThread());
-        assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false));
-    }
-
-    @SuppressWarnings("all")
-    public static Thread currentThread() {
-        return Thread.currentThread();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean threadIsInterrupted(Thread thread) {
-        return thread.isInterrupted();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean threadInterrupted() {
-        return Thread.interrupted();
-    }
-
-    @Test
-    public void testSystemSubstitutions() {
-        test("systemTime");
-        test("systemIdentityHashCode");
-
-        SystemSubstitutions.currentTimeMillis();
-        SystemSubstitutions.nanoTime();
-        for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-            assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static long systemTime() {
-        return System.currentTimeMillis() + System.nanoTime();
-    }
-
-    @SuppressWarnings("all")
-    public static int systemIdentityHashCode(Object obj) {
-        return System.identityHashCode(obj);
-    }
-
-    private static class TestClassA {
-    }
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/InstalledCodeExecuteHelperTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +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.hotspot;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
-
-    private static final int ITERATIONS = 100000000;
-
-    @Ignore
-    @Test
-    public void test1() throws NoSuchMethodException, SecurityException {
-
-        final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class);
-        final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod);
-        HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod));
-
-        final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class);
-        final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod);
-        HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod));
-
-        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
-        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod);
-        HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
-
-        System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null));
-
-        long nmethod = fooCode.getnmethod();
-        long metaspacemethod = fooJavaMethod.getMetaspaceMethod();
-
-        System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod));
-
-        System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod));
-
-    }
-
-    public static Long bench(long nmethod, long metaspacemethod) {
-        long start = System.currentTimeMillis();
-
-        for (int i = 0; i < ITERATIONS; i++) {
-            HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null);
-        }
-
-        long end = System.currentTimeMillis();
-        return (end - start);
-    }
-
-    public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
-        return 42;
-    }
-
-    public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
-        return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,238 @@
+/*
+ * 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.test;
+
+import static org.junit.Assert.*;
+
+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.graph.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}.
+ */
+public class ArrayCopyIntrinsificationTest extends GraalCompilerTest {
+
+    @Override
+    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
+        int nodeCount = graph.getNodeCount();
+        InstalledCode result = super.getCode(method, graph);
+        boolean graphWasProcessed = nodeCount != graph.getNodeCount();
+        if (graphWasProcessed) {
+            if (mustIntrinsify) {
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Invoke) {
+                        Invoke invoke = (Invoke) node;
+                        Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
+                        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()));
+                    }
+                }
+            } else {
+                boolean found = false;
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Invoke) {
+                        Invoke invoke = (Invoke) node;
+                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
+                        JavaMethod callee = directCall.target();
+                        if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
+                            found = true;
+                        } else {
+                            fail("found invoke to some method other than arraycopy: " + callee);
+                        }
+                    }
+                }
+                Assert.assertTrue("did not find invoke to arraycopy", found);
+            }
+        }
+        return result;
+    }
+
+    boolean mustIntrinsify = true;
+
+    @Test
+    public void test0() {
+        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
+        // Array store checks
+        test("genericArraycopy", new Object(), 0, new Object[0], 0, 0);
+        test("genericArraycopy", new Object[0], 0, new Object(), 0, 0);
+
+        mustIntrinsify = true;
+    }
+
+    @Test
+    public void test1() {
+        String name = "intArraycopy";
+        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        // Null checks
+        test(name, null, 0, src, 0, 0);
+        test(name, src, 0, null, 0, 0);
+        // Bounds checks
+        test(name, src, 0, src, 0, -1);
+        test(name, src, 0, src, 0, src.length + 1);
+    }
+
+    @Test
+    public void testByte() {
+        byte[] src = {-1, 0, 1, 2, 3, 4};
+        testHelper("byteArraycopy", src);
+    }
+
+    @Test
+    public void testChar() {
+        char[] src = "some string of chars".toCharArray();
+        testHelper("charArraycopy", src);
+    }
+
+    @Test
+    public void testShort() {
+        short[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("shortArraycopy", src);
+    }
+
+    @Test
+    public void testInt() {
+        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("intArraycopy", src);
+    }
+
+    @Test
+    public void testFloat() {
+        float[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("floatArraycopy", src);
+    }
+
+    @Test
+    public void testLong() {
+        long[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("longArraycopy", src);
+    }
+
+    @Test
+    public void testDouble() {
+        double[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("doubleArraycopy", src);
+    }
+
+    @Test
+    public void testObject() {
+        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
+
+        Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()};
+        testHelper("objectArraycopy", src);
+
+        mustIntrinsify = true;
+    }
+
+    @Test
+    public void testObjectExact() {
+        Integer[] src = {1, 2, 3, 4};
+        testHelper("objectArraycopyExact", src);
+    }
+
+    private static Object newArray(Object proto, int length) {
+        assert proto != null;
+        assert proto.getClass().isArray();
+        return Array.newInstance(proto.getClass().getComponentType(), length);
+    }
+
+    private void testHelper(String name, Object src) {
+        int srcLength = Array.getLength(src);
+
+        // Complete array copy
+        test(name, src, 0, newArray(src, srcLength), 0, srcLength);
+
+        for (int length : new int[]{0, 1, srcLength - 1, srcLength}) {
+            // Partial array copying
+            test(name, src, 0, newArray(src, length), 0, length);
+            test(name, src, srcLength - length, newArray(src, length), 0, length);
+            test(name, src, 0, newArray(src, srcLength), 0, length);
+        }
+    }
+
+    public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.*;
+
+/**
+ * Tests {@link CompileTheWorld} functionality.
+ */
+public class CompileTheWorldTest extends GraalCompilerTest {
+
+    @Test
+    public void testRtJar() throws Throwable {
+        // Compile a couple classes in rt.jar
+        String file = System.getProperty("java.home") + "/lib/rt.jar";
+        new CompileTheWorld(file, 1, 5).compile();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.hotspot.test;
+
+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.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class HotSpotInstalledCodeTest extends GraalCompilerTest {
+
+    private static final int ITERATION_COUNT = 100000;
+
+    @Test
+    public void testInstallCodeInvalidation() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        Object result;
+        try {
+            result = installedCode.execute("a", "b", "c");
+            assertEquals(43, result);
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+        Assert.assertTrue(installedCode.isValid());
+        installedCode.invalidate();
+        Assert.assertFalse(installedCode.isValid());
+        try {
+            result = installedCode.execute(null, null, null);
+            Assert.fail("Code was not invalidated");
+        } catch (InvalidInstalledCodeException e) {
+        }
+        Assert.assertFalse(installedCode.isValid());
+    }
+
+    @Test
+    public void testInstalledCodeCalledFromCompiledCode() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        try {
+            for (int i = 0; i < ITERATION_COUNT; ++i) {
+                installedCode.execute("a", "b", "c");
+            }
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static Object foo(Object a1, Object a2, Object a3) {
+        return 42;
+    }
+
+    @SuppressWarnings("unused")
+    public static Object otherFoo(Object a1, Object a2, Object a3) {
+        return 43;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,165 @@
+/*
+ * 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific {@link MethodSubstitution}s.
+ */
+public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest {
+
+    @Test
+    public void testObjectSubstitutions() {
+        test("getClass_");
+        test("objectHashCode");
+
+        Object obj = new Object();
+
+        assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string"));
+        assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj));
+    }
+
+    @SuppressWarnings("all")
+    public static boolean getClass_(Object obj, Class<?> clazz) {
+        return obj.getClass() == clazz;
+    }
+
+    @SuppressWarnings("all")
+    public static int objectHashCode(TestClassA obj) {
+        return obj.hashCode();
+    }
+
+    @Test
+    public void testClassSubstitutions() {
+        test("getModifiers");
+        test("isInstance");
+        test("isInterface");
+        test("isArray");
+        test("isPrimitive");
+        test("getSuperClass");
+        test("getComponentType");
+
+        for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
+            assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
+            assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
+            assertEquals(c.isArray(), ClassSubstitutions.isArray(c));
+            assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c));
+            assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c));
+            assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c));
+            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
+                assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
+            }
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static int getModifiers(Class<?> clazz) {
+        return clazz.getModifiers();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isInstance(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isInterface(Class<?> clazz) {
+        return clazz.isInterface();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isArray(Class<?> clazz) {
+        return clazz.isArray();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isPrimitive(Class<?> clazz) {
+        return clazz.isPrimitive();
+    }
+
+    @SuppressWarnings("all")
+    public static Class<?> getSuperClass(Class<?> clazz) {
+        return clazz.getSuperclass();
+    }
+
+    @SuppressWarnings("all")
+    public static Class<?> getComponentType(Class<?> clazz) {
+        return clazz.getComponentType();
+    }
+
+    @Test
+    public void testThreadSubstitutions() {
+        test("currentThread");
+        test("threadIsInterrupted");
+        test("threadInterrupted");
+
+        Thread currentThread = Thread.currentThread();
+        assertEquals(currentThread, ThreadSubstitutions.currentThread());
+        assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false));
+    }
+
+    @SuppressWarnings("all")
+    public static Thread currentThread() {
+        return Thread.currentThread();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean threadIsInterrupted(Thread thread) {
+        return thread.isInterrupted();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean threadInterrupted() {
+        return Thread.interrupted();
+    }
+
+    @Test
+    public void testSystemSubstitutions() {
+        test("systemTime");
+        test("systemIdentityHashCode");
+
+        SystemSubstitutions.currentTimeMillis();
+        SystemSubstitutions.nanoTime();
+        for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
+            assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static long systemTime() {
+        return System.currentTimeMillis() + System.nanoTime();
+    }
+
+    @SuppressWarnings("all")
+    public static int systemIdentityHashCode(Object obj) {
+        return System.identityHashCode(obj);
+    }
+
+    private static class TestClassA {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,98 @@
+/*
+ * 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.hotspot.test;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+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.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
+
+    private static final int ITERATIONS = 100000;
+    private final MetaAccessProvider metaAccessProvider;
+    Object[] argsToBind;
+
+    public InstalledCodeExecuteHelperTest() {
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+    }
+
+    @Test
+    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+
+        argsToBind = new Object[]{fooCode};
+
+        final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class);
+        final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
+
+        Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode));
+
+        Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0]));
+
+    }
+
+    public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException {
+        int val = 0;
+        for (int j = 0; j < 100; j++) {
+            for (int i = 0; i < ITERATIONS; i++) {
+                val = (Integer) code.execute(null, null, null);
+            }
+        }
+        return val;
+    }
+
+    public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
+        return 42;
+    }
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        StructuredGraph graph = super.parse(m);
+        if (argsToBind != null) {
+            Object receiver = isStatic(m.getModifiers()) ? null : this;
+            Object[] args = argsWithReceiver(receiver, argsToBind);
+            JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m));
+            assert parameterTypes.length == args.length;
+            for (int i = 0; i < argsToBind.length; i++) {
+                LocalNode local = graph.getLocal(i);
+                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]);
+                ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph);
+                local.replaceAtUsages(replacement);
+            }
+        }
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,20 +22,22 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.nodes.StructuredGraph.*;
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
+import java.lang.reflect.Modifier;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
-import static com.oracle.graal.nodes.StructuredGraph.*;
 
 public final class CompilationTask implements Runnable, Comparable<CompilationTask> {
 
@@ -133,6 +135,9 @@
                 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(),
                                 entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "));
             }
+            if (GraalOptions.HotSpotPrintCompilation) {
+                printCompilation();
+            }
 
             CompilationResult result = null;
             TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
@@ -143,7 +148,8 @@
                     @Override
                     public CompilationResult call() throws Exception {
                         graalRuntime.evictDeoptedGraphs();
-                        StructuredGraph graph = (StructuredGraph) method.getCompilerStorage().get(MethodSubstitution.class);
+                        Replacements replacements = graalRuntime.getReplacements();
+                        StructuredGraph graph = replacements.getMethodSubstitution(method);
                         if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
                             graph = new StructuredGraph(method, entryBCI);
                         } else {
@@ -151,7 +157,7 @@
                             graph = graph.copy();
                         }
                         InlinedBytecodes.add(method.getCodeSize());
-                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan,
+                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), replacements, graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan,
                                         optimisticOpts, method.getSpeculationLog());
                     }
                 });
@@ -162,7 +168,7 @@
                 }
             }
 
-            installMethod(result);
+            installMethod(result, null);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
             if (GraalOptions.ExitVMOnBailout) {
@@ -182,12 +188,22 @@
         stats.finish(method);
     }
 
-    private void installMethod(final CompilationResult compResult) {
+    /**
+     * Print a HotSpot-style compilation message to the console.
+     */
+    private void printCompilation() {
+        final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
+        final int mod = method.getModifiers();
+        TTY.println(String.format("%7d %4d %c%c%c%c%c       %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ',
+                        MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
+    }
+
+    private void installMethod(final CompilationResult compResult, final Graph graph) {
         Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() {
 
             @Override
             public void run() {
-                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult);
+                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,252 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.*;
+import java.util.Enumeration;
+import java.util.jar.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.Bytecodes;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * This class implements compile-the-world functionality in Graal.
+ */
+public final class CompileTheWorld {
+
+    /**
+     * This is our magic token to trigger reading files from the boot class path.
+     */
+    public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
+
+    // Some runtime instances we need.
+    private final HotSpotGraalRuntime graalRuntime = HotSpotGraalRuntime.getInstance();
+    private final VMToCompilerImpl vmToCompiler = (VMToCompilerImpl) graalRuntime.getVMToCompiler();
+
+    /** List of Zip/Jar files to compile (see {@link GraalOptions#CompileTheWorld}. */
+    private final String files;
+
+    /** Class index to start compilation at (see {@link GraalOptions#CompileTheWorldStartAt}. */
+    private final int startAt;
+
+    /** Class index to stop compilation at (see {@link GraalOptions#CompileTheWorldStopAt}. */
+    private final int stopAt;
+
+    // Counters
+    private int classFileCounter = 0;
+    private int compiledMethodsCounter = 0;
+    private long compileTime = 0;
+
+    /**
+     * Create a compile-the-world instance with default values from
+     * {@link GraalOptions#CompileTheWorld}, {@link GraalOptions#CompileTheWorldStartAt} and
+     * {@link GraalOptions#CompileTheWorldStopAt}.
+     */
+    public CompileTheWorld() {
+        this(GraalOptions.CompileTheWorld, GraalOptions.CompileTheWorldStartAt, GraalOptions.CompileTheWorldStopAt);
+    }
+
+    /**
+     * Create a compile-the-world instance.
+     * 
+     * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile
+     * @param startAt index of the class file to start compilation at
+     * @param stopAt index of the class file to stop compilation at
+     */
+    public CompileTheWorld(String files, int startAt, int stopAt) {
+        this.files = files;
+        this.startAt = startAt;
+        this.stopAt = stopAt;
+
+        // We don't want the VM to exit when a method fails to compile.
+        GraalOptions.ExitVMOnException = false;
+    }
+
+    /**
+     * Compile all methods in all classes in the Zip/Jar files in
+     * {@link GraalOptions#CompileTheWorld}. If the GraalOptions.CompileTheWorld contains the magic
+     * token {@link CompileTheWorld#SUN_BOOT_CLASS_PATH} passed up from HotSpot we take the files
+     * from the boot class path.
+     * 
+     * @throws Throwable
+     */
+    public void compile() throws Throwable {
+        if (SUN_BOOT_CLASS_PATH.equals(files)) {
+            final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
+            String bcpFiles = "";
+            for (int i = 0; i < entries.length; i++) {
+                final String entry = entries[i];
+
+                // We stop at rt.jar, unless it is the first boot class path entry.
+                if (entry.endsWith("rt.jar") && (i > 0)) {
+                    break;
+                }
+                if (i > 0) {
+                    bcpFiles += File.pathSeparator;
+                }
+                bcpFiles += entry;
+            }
+            compile(bcpFiles);
+        } else {
+            compile(files);
+        }
+    }
+
+    /**
+     * Compile all methods in all classes in the Zip/Jar files passed.
+     * 
+     * @param fileList {@link File#pathSeparator} separated list of Zip/Jar files to compile
+     * @throws Throwable
+     */
+    private void compile(String fileList) throws Throwable {
+        final String[] entries = fileList.split(File.pathSeparator);
+
+        for (int i = 0; i < entries.length; i++) {
+            final String entry = entries[i];
+
+            // For now we only compile all methods in all classes in zip/jar files.
+            if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
+                TTY.println("CompileTheWorld : Skipped classes in " + entry);
+                TTY.println();
+                continue;
+            }
+
+            TTY.println("CompileTheWorld : Compiling all classes in " + entry);
+            TTY.println();
+
+            URL url = new URL("jar", "", "file:" + entry + "!/");
+            ClassLoader loader = new URLClassLoader(new URL[]{url});
+
+            JarFile jarFile = new JarFile(entry);
+            Enumeration<JarEntry> e = jarFile.entries();
+
+            while (e.hasMoreElements()) {
+                JarEntry je = e.nextElement();
+                if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                    continue;
+                }
+
+                // Are we done?
+                if (classFileCounter >= stopAt) {
+                    break;
+                }
+
+                String className = je.getName().substring(0, je.getName().length() - ".class".length());
+                className = className.replace('/', '.');
+                classFileCounter++;
+
+                try {
+                    // Load and initialize class
+                    Class<?> javaClass = Class.forName(className, true, loader);
+
+                    // Pre-load all classes in the constant pool.
+                    try {
+                        HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
+                        ConstantPool constantPool = objectType.constantPool();
+                        for (int cpi = 1; cpi < constantPool.length(); cpi++) {
+                            constantPool.loadReferencedType(cpi, Bytecodes.LDC);
+                        }
+                    } catch (Throwable t) {
+                        // If something went wrong during pre-loading we just ignore it.
+                        TTY.println("CompileTheWorld (%d) : Preloading failed for %s", classFileCounter, className);
+                    }
+
+                    // Are we compiling this class?
+                    if (classFileCounter >= startAt) {
+                        TTY.println("CompileTheWorld (%d) : %s", classFileCounter, className);
+
+                        // Enqueue each constructor/method in the class for compilation.
+                        for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
+                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaConstructor(constructor);
+                            if (canBeCompiled(javaMethod, constructor.getModifiers())) {
+                                compileMethod(javaMethod);
+                            }
+                        }
+                        for (Method method : javaClass.getDeclaredMethods()) {
+                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaMethod(method);
+                            if (canBeCompiled(javaMethod, method.getModifiers())) {
+                                compileMethod(javaMethod);
+                            }
+                        }
+                    }
+                } catch (Throwable t) {
+                    TTY.println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
+                }
+            }
+            jarFile.close();
+        }
+
+        TTY.println();
+        TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
+    }
+
+    /**
+     * Helper method to schedule a method for compilation and gather some statistics.
+     */
+    private void compileMethod(HotSpotResolvedJavaMethod method) {
+        try {
+            long start = System.currentTimeMillis();
+            vmToCompiler.compileMethod(method, StructuredGraph.INVOCATION_ENTRY_BCI, true, 10);
+            compileTime += (System.currentTimeMillis() - start);
+            compiledMethodsCounter++;
+            method.reprofile();  // makes the method also not-entrant
+        } catch (Throwable t) {
+            // Catch everything and print a message
+            TTY.println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method));
+            t.printStackTrace(TTY.cachedOut);
+        }
+    }
+
+    /**
+     * Helper method for CompileTheWorld to determine if a method should be compiled (Cf.
+     * CompilationPolicy::can_be_compiled).
+     * 
+     * @return true if it can be compiled, false otherwise
+     */
+    private static boolean canBeCompiled(HotSpotResolvedJavaMethod javaMethod, int modifiers) {
+        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+            return false;
+        }
+        // This number is from HotSpot:
+        final int hugeMethodLimit = 8000;
+        if (javaMethod.getCodeSize() > hugeMethodLimit) {
+            return false;
+        }
+        // Skip @Snippets for now
+        if (javaMethod.getAnnotation(Snippet.class) != null) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Mon Apr 15 08:51:19 2013 +0200
@@ -67,7 +67,7 @@
     }
 
     private static Site[] getSortedSites(CompilationResult target) {
-        List<?>[] lists = new List<?>[]{target.getSafepoints(), target.getDataReferences(), target.getMarks()};
+        List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataReferences(), target.getMarks()};
         int count = 0;
         for (List<?> list : lists) {
             count += list.size();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 15 08:51:19 2013 +0200
@@ -119,6 +119,7 @@
 
     protected final HotSpotRuntime runtime;
     protected final TargetDescription target;
+    protected final Replacements replacements;
 
     private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface;
     private volatile HotSpotGraphCache cache;
@@ -138,6 +139,19 @@
         compilerToVm.initializeConfiguration(config);
         config.check();
 
+        // Set some global options:
+        if (config.compileTheWorld) {
+            GraalOptions.CompileTheWorld = CompileTheWorld.SUN_BOOT_CLASS_PATH;
+        }
+        if (config.compileTheWorldStartAt != 1) {
+            GraalOptions.CompileTheWorldStartAt = config.compileTheWorldStartAt;
+        }
+        if (config.compileTheWorldStopAt != Integer.MAX_VALUE) {
+            GraalOptions.CompileTheWorldStopAt = config.compileTheWorldStopAt;
+        }
+        GraalOptions.HotSpotPrintCompilation = config.printCompilation;
+        GraalOptions.HotSpotPrintInlining = config.printInlining;
+
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
             printConfig(config);
         }
@@ -148,6 +162,11 @@
 
         runtime = createRuntime();
 
+        // Replacements cannot have speculative optimizations since they have
+        // to be valid for the entire run of the VM.
+        Assumptions assumptions = new Assumptions(false);
+        replacements = new HotSpotReplacementsImpl(runtime, assumptions, runtime.getGraalRuntime().getTarget());
+
         backend = createBackend();
         GraalOptions.StackShadowPages = config.stackShadowPages;
         if (GraalOptions.CacheGraphs) {
@@ -239,6 +258,10 @@
         return runtime;
     }
 
+    public Replacements getReplacements() {
+        return replacements;
+    }
+
     public void evictDeoptedGraphs() {
         if (cache != null) {
             long[] deoptedGraphs = getCompilerToVM().getDeoptedLeafGraphIds();
@@ -269,6 +292,9 @@
         if (clazz == HotSpotRuntime.class) {
             return (T) runtime;
         }
+        if (clazz == Replacements.class) {
+            return (T) replacements;
+        }
         if (clazz == Backend.class) {
             return (T) getBackend();
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * Filters certain method substitutions based on whether there is underlying hardware support for
+ * them.
+ */
+public class HotSpotReplacementsImpl extends ReplacementsImpl {
+
+    private final HotSpotVMConfig config;
+
+    public HotSpotReplacementsImpl(HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) {
+        super(runtime, assumptions, target);
+        this.config = runtime.config;
+    }
+
+    @Override
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
+        if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) {
+            if (substituteMethod.getName().equals("bitCount")) {
+                if (!config.usePopCountInstruction) {
+                    return null;
+                }
+            }
+        } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) {
+            if (!config.useAESIntrinsics) {
+                return null;
+            }
+            assert config.aescryptEncryptBlockStub != 0L;
+            assert config.aescryptDecryptBlockStub != 0L;
+            assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
+            assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
+        }
+        return super.registerMethodSubstitution(originalMethod, substituteMethod);
+    }
+
+    @Override
+    public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        int intrinsicId = hsMethod.intrinsicId();
+        if (intrinsicId != 0) {
+            if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+                return MethodHandleInvokeBasicNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+                return MethodHandleLinkToInterfaceNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+                return MethodHandleLinkToSpecialNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+                return MethodHandleLinkToStaticNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+                return MethodHandleLinkToVirtualNode.class;
+            }
+        }
+        return super.getMacroSubstitution(method);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsInstaller.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * 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;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.replacements.*;
-
-/**
- * Filters certain method substitutions based on whether there is underlying hardware support for them.
- */
-public class HotSpotReplacementsInstaller extends ReplacementsInstaller {
-
-    private final HotSpotVMConfig config;
-
-    public HotSpotReplacementsInstaller(HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) {
-        super(runtime, assumptions, target);
-        this.config = runtime.config;
-    }
-
-    @Override
-    protected void installMethodSubstitution(Member originalMethod, Method substituteMethod) {
-        if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) {
-            if (substituteMethod.getName().equals("bitCount")) {
-                if (!config.usePopCountInstruction) {
-                    return;
-                }
-            }
-        } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) {
-            if (!config.useAESIntrinsics) {
-                return;
-            }
-            assert config.aescryptEncryptBlockStub != 0L;
-            assert config.aescryptDecryptBlockStub != 0L;
-            assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
-            assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
-        }
-        super.installMethodSubstitution(originalMethod, substituteMethod);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.stubs.*;
 
@@ -79,17 +80,19 @@
     }
 
     public void setStub(Stub stub) {
-        assert address == 0L : "cannot stub for linkage that already has an address: " + this;
+        assert address == 0L : "cannot set stub for linkage that already has an address: " + this;
         this.stub = stub;
     }
 
-    public void setAddress(long address) {
-        assert this.address == 0L : "cannot re-initialize address of " + this;
-        this.address = address;
+    public void finalizeAddress(Backend backend) {
+        if (address == 0) {
+            assert stub != null : "linkage without an address must be a stub";
+            address = stub.getAddress(backend);
+        }
     }
 
-    public long getAddress() {
-        assert address != 0L : "address not yet initialized for " + this;
-        return address;
+    @Override
+    public boolean preservesRegisters() {
+        return stub == null;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -37,6 +37,11 @@
     public int codeEntryAlignment;
     public boolean verifyOops;
     public boolean ciTime;
+    public boolean compileTheWorld;
+    public int compileTheWorldStartAt;
+    public int compileTheWorldStopAt;
+    public boolean printCompilation;
+    public boolean printInlining;
     public boolean useFastLocking;
     public boolean useTLAB;
     public boolean useBiasedLocking;
@@ -185,6 +190,11 @@
     public int methodAccessFlagsOffset;
 
     /**
+     * Offset of _intrinsic_id in a metaspace Method object.
+     */
+    public int methodIntrinsicIdOffset;
+
+    /**
      * Offset of _max_locals in a metaspace Method object.
      */
     public int methodMaxLocalsOffset;
@@ -376,6 +386,12 @@
     public int deoptActionMakeNotEntrant;
     public int deoptActionMakeNotCompilable;
 
+    public int vmIntrinsicInvokeBasic;
+    public int vmIntrinsicLinkToVirtual;
+    public int vmIntrinsicLinkToStatic;
+    public int vmIntrinsicLinkToSpecial;
+    public int vmIntrinsicLinkToInterface;
+
     public void check() {
         assert codeEntryAlignment > 0;
         assert stackShadowPages > 0;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 15 08:51:19 2013 +0200
@@ -128,6 +128,8 @@
      */
     JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
+    int constantPoolLength(HotSpotResolvedObjectType pool);
+
     Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     JavaMethod lookupMethodInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
@@ -138,6 +140,8 @@
 
     void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
 
+    Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
     // Must be kept in sync with enum in graalEnv.hpp
     public enum CodeInstallResult {
         OK, DEPENDENCIES_FAILED, CACHE_FULL
@@ -199,9 +203,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException;
 
     int getVtableEntryOffset(long metaspaceMethod);
 
@@ -221,4 +225,8 @@
      * @param metaspaceMethod the metaspace Method object
      */
     void reprofile(long metaspaceMethod);
+
+    void invalidateInstalledCode(long nativeMethod);
+
+    boolean isInstalledCodeValid(long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -79,6 +79,9 @@
     public native JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
     @Override
+    public native int constantPoolLength(HotSpotResolvedObjectType pool);
+
+    @Override
     public native Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     @Override
@@ -133,10 +136,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
-
-    @Override
-    public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod);
 
     @Override
     public native int getVtableEntryOffset(long metaspaceMethod);
@@ -158,4 +158,27 @@
 
     @Override
     public native void reprofile(long metaspaceMethod);
+
+    @Override
+    public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
+    @Override
+    public native void invalidateInstalledCode(long nativeMethod);
+
+    @Override
+    public native boolean isInstalledCodeValid(long nativeMethod);
+
+    @Override
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException {
+        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
+    }
+
+    /**
+     * Direct call to the given nativeMethod with three object arguments and an object return value.
+     * This method does not have an implementation on the C++ side, but its entry points (from
+     * interpreter and from compiled code) are directly pointing to a manually generated assembly
+     * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
+     * verified entry point of the given native method.
+     */
+    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.bridge;
 
+import java.io.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
@@ -65,10 +66,10 @@
         return (int) (v / t);
     }
 
-    public void printAll(String label) {
+    public void printAll(String label, PrintStream stream) {
         MetricRateInPhase rs = this;
         while (rs != null) {
-            System.out.println(label + "@" + rs.phase + ": " + rs.rate());
+            stream.println(label + "@" + rs.phase + ": " + rs.rate());
             rs = rs.previous;
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,8 +34,23 @@
  */
 public interface VMToCompiler {
 
+    /**
+     * Compiles a method to machine code. This method is called from the VM
+     * (VMToCompiler::compileMethod).
+     * 
+     * @return true if the method is in the queue (either added to the queue or already in the
+     *         queue)
+     */
     boolean compileMethod(long metaspaceMethod, HotSpotResolvedObjectType holder, int entryBCI, boolean blocking, int priority) throws Throwable;
 
+    /**
+     * Compiles a method to machine code.
+     * 
+     * @return true if the method is in the queue (either added to the queue or already in the
+     *         queue)
+     */
+    boolean compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, boolean blocking, int priority) throws Throwable;
+
     void shutdownCompiler() throws Throwable;
 
     void startCompiler() throws Throwable;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,10 +34,10 @@
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -45,6 +45,7 @@
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.debug.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.printer.*;
@@ -146,19 +147,24 @@
 
         // Install intrinsics.
         final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class);
+        final Replacements replacements = graalRuntime.getCapability(Replacements.class);
         if (GraalOptions.Intrinsify) {
-            Debug.scope("InstallReplacements", new Object[]{new DebugDumpScope("InstallReplacements")}, new Runnable() {
+            Debug.scope("RegisterReplacements", new Object[]{new DebugDumpScope("RegisterReplacements")}, new Runnable() {
 
                 @Override
                 public void run() {
-                    // Replacements cannot have speculative optimizations since they have
-                    // to be valid for the entire run of the VM.
-                    Assumptions assumptions = new Assumptions(false);
-                    ReplacementsInstaller installer = new HotSpotReplacementsInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget());
-                    for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) {
-                        provider.installReplacements(installer);
+                    ServiceLoader<ReplacementsProvider> serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class);
+                    for (ReplacementsProvider provider : serviceLoader) {
+                        provider.registerReplacements(replacements);
                     }
-                    runtime.installReplacements(graalRuntime.getBackend(), installer, assumptions);
+                    runtime.registerReplacements(replacements);
+                    if (GraalOptions.BootstrapReplacements) {
+                        for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
+                            replacements.getMacroSubstitution(method);
+                            replacements.getMethodSubstitution(method);
+                            replacements.getSnippet(method);
+                        }
+                    }
                 }
             });
 
@@ -200,9 +206,22 @@
             t.start();
         }
 
-        if (GraalOptions.BenchmarkDynamicCounters) {
-            System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n")));
-            System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends:   ", "\n")));
+        if (GraalOptions.BenchmarkDynamicCounters != null) {
+            String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(",");
+            if (arguments.length == 0 || (arguments.length % 3) != 0) {
+                throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)");
+            }
+            for (int i = 0; i < arguments.length; i += 3) {
+                if (arguments[i].equals("err")) {
+                    System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, arguments[i + 1], arguments[i + 2])));
+                } else if (arguments[i].equals("out")) {
+                    System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, arguments[i + 1], arguments[i + 2])));
+                } else {
+                    throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out");
+                }
+                // dacapo: "err, starting =====, PASSED in "
+                // specjvm2008: "out,Iteration ~ (~s) begins: ,Iteration ~ (~s) ends:   "
+            }
             DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/";
             DynamicCounterNode.enabled = true;
         }
@@ -217,8 +236,8 @@
         private long startTime;
         private boolean waitingForEnd;
 
-        private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) {
-            super(delegate, patterns);
+        private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) {
+            super(delegate, new String[]{start, end, "\n"});
         }
 
         @Override
@@ -374,6 +393,10 @@
         System.gc();
         phaseTransition("bootstrap2");
 
+        if (GraalOptions.CompileTheWorld != null) {
+            new CompileTheWorld().compile();
+            System.exit(0);
+        }
     }
 
     private MetricRateInPhase parsedBytecodesPerSecond;
@@ -441,8 +464,8 @@
         phaseTransition("final");
 
         if (graalRuntime.getConfig().ciTime) {
-            parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond");
-            inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond");
+            parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond", System.out);
+            inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond", System.out);
         }
 
         SnippetCounter.printGroups(TTY.out().out());
@@ -716,6 +739,7 @@
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
+        phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
         return phasePlan;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Mon Apr 15 08:51:19 2013 +0200
@@ -41,7 +41,9 @@
 
     public CountingProxy(T delegate) {
         assert ENABLED;
+        // CheckStyle: stop system..print check
         System.out.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created");
+        // CheckStyle: resume system..print check
         this.delegate = delegate;
         proxies.add(this);
     }
@@ -92,6 +94,7 @@
         }
     }
 
+    // CheckStyle: stop system..print check
     protected void print() {
         long sum = 0;
         for (Map.Entry<Method, AtomicLong> entry : calls.entrySet()) {
@@ -102,4 +105,5 @@
         }
         System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum);
     }
+    // CheckStyle: resume system..print check
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java	Mon Apr 15 08:51:19 2013 +0200
@@ -70,6 +70,7 @@
         }
     }
 
+    // CheckStyle: stop system..print check
     public static void info(String message) {
         if (ENABLED) {
             log(message);
@@ -124,6 +125,8 @@
         }
     }
 
+    // CheckStyle: resume system..print check
+
     private static String[] spaces = new String[50];
 
     private static String space(int count) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -39,6 +40,11 @@
     }
 
     @Override
+    public int length() {
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().constantPoolLength(type);
+    }
+
+    @Override
     public Object lookupConstant(int cpi) {
         assert cpi != 0;
         Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupConstantInPool(type, cpi);
@@ -51,6 +57,12 @@
     }
 
     @Override
+    public Object lookupAppendix(int cpi, int opcode) {
+        assert Bytecodes.isInvoke(opcode);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode);
+    }
+
+    @Override
     public JavaMethod lookupMethod(int cpi, int opcode) {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -39,11 +40,13 @@
 
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
+    private final Graph graph;
     long nmethod;
     long start;
 
-    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) {
+    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) {
         this.method = method;
+        this.graph = graph;
         this.isDefault = isDefault;
     }
 
@@ -51,10 +54,14 @@
         return isDefault;
     }
 
-    public long getnmethod() {
+    public long getMethodAddress() {
         return nmethod;
     }
 
+    public Graph getGraph() {
+        return graph;
+    }
+
     @Override
     public ResolvedJavaMethod getMethod() {
         return method;
@@ -62,7 +69,12 @@
 
     @Override
     public boolean isValid() {
-        return nmethod != 0;
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod);
+    }
+
+    @Override
+    public void invalidate() {
+        HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod);
     }
 
     @Override
@@ -71,12 +83,12 @@
     }
 
     @Override
-    public Object execute(Object arg1, Object arg2, Object arg3) {
+    public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
         assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
         assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
     }
 
     private boolean checkArgs(Object... args) {
@@ -94,9 +106,9 @@
     }
 
     @Override
-    public Object executeVarargs(Object... args) {
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         assert checkArgs(args);
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod);
     }
 
     @Override
@@ -108,8 +120,4 @@
     public byte[] getCode() {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod);
     }
-
-    public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Apr 15 08:51:19 2013 +0200
@@ -364,12 +364,12 @@
             }
 
             totalCount += getTypesNotRecordedExecutionCount(data, position);
-            return createTypeProfile(types, counts, totalCount, entries);
+            return createTypeProfile(getNullSeen(data, position), types, counts, totalCount, entries);
         }
 
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
-        private static JavaTypeProfile createTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
+        private static JavaTypeProfile createTypeProfile(TriState nullSeen, ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
             if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
                 return null;
             }
@@ -387,7 +387,7 @@
 
             double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
             assert notRecordedTypeProbability == 0 || entries == config.typeProfileWidth;
-            return new JavaTypeProfile(notRecordedTypeProbability, ptypes);
+            return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
         }
 
         private static int getReceiverOffset(int row) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -51,6 +53,6 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + holder.getName() + ". " + name + ", unresolved>";
+        return format("HotSpotMethod<%H.%n(%p), unresolved>", this);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,6 +23,8 @@
 
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
@@ -150,7 +152,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotField<" + MetaUtil.format("%h.%n", this) + ":" + offset + ">";
+        return format("HotSpotField<%H.%n %t:", this) + offset + ">";
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.graph.FieldIntrospection.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
@@ -186,7 +187,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">";
+        return format("HotSpotMethod<%H.%n(%p)>", this);
     }
 
     public int getCompiledCodeSize() {
@@ -361,4 +362,51 @@
         }
         return speculationLog;
     }
+
+    public int intrinsicId() {
+        HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
+        return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff;
+    }
+
+    @Override
+    public Constant invoke(Constant receiver, Constant[] arguments) {
+        assert !isConstructor();
+        Method javaMethod = toJava();
+        javaMethod.setAccessible(true);
+
+        Object[] objArguments = new Object[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            objArguments[i] = arguments[i].asBoxedValue();
+        }
+        Object objReceiver = receiver != null ? receiver.asObject() : null;
+
+        try {
+            Object objResult = javaMethod.invoke(objReceiver, objArguments);
+            return javaMethod.getReturnType() == void.class ? null : Constant.forBoxed(getSignature().getReturnKind(), objResult);
+
+        } catch (IllegalAccessException | InvocationTargetException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+
+    @Override
+    public Constant newInstance(Constant[] arguments) {
+        assert isConstructor();
+        Constructor javaConstructor = toJavaConstructor();
+        javaConstructor.setAccessible(true);
+
+        Object[] objArguments = new Object[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            objArguments[i] = arguments[i].asBoxedValue();
+        }
+
+        try {
+            Object objResult = javaConstructor.newInstance(objArguments);
+            assert objResult != null;
+            return Constant.forObject(objResult);
+
+        } catch (IllegalAccessException | InvocationTargetException | InstantiationException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -135,7 +135,6 @@
         assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies);
         assert javaMirror.isArray() == isArray();
         assert javaMirror.isInterface() == isInterface();
-        // System.out.println("0x" + Long.toHexString(metaspaceKlass) + ": " + name);
     }
 
     @Override
@@ -520,4 +519,31 @@
         final Class<?> encl = mirror().getEnclosingClass();
         return encl == null ? null : fromClass(encl);
     }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        Constructor[] constructors = javaMirror.getDeclaredConstructors();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
+        for (int i = 0; i < constructors.length; i++) {
+            result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaConstructor(constructors[i]);
+            assert result[i].isConstructor();
+        }
+        return result;
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        Method[] methods = javaMirror.getDeclaredMethods();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
+        for (int i = 0; i < methods.length; i++) {
+            result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaMethod(methods[i]);
+            assert !result[i].isConstructor();
+        }
+        return result;
+    }
+
+    @Override
+    public Constant newArray(int length) {
+        return Constant.forObject(Array.newInstance(javaMirror, length));
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -210,4 +210,19 @@
     public ResolvedJavaType getEnclosingType() {
         return null;
     }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public Constant newArray(int length) {
+        return Constant.forObject(Array.newInstance(javaMirror, length));
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Apr 15 08:51:19 2013 +0200
@@ -30,12 +30,14 @@
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
-import com.oracle.graal.replacements.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 
@@ -46,11 +48,10 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Safepoint;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
 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.*;
@@ -63,12 +64,14 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -87,9 +90,8 @@
     private NewObjectSnippets.Templates newObjectSnippets;
     private MonitorSnippets.Templates monitorSnippets;
     private WriteBarrierSnippets.Templates writeBarrierSnippets;
-
-    private NewInstanceStub newInstanceStub;
-    private NewArrayStub newArrayStub;
+    private BoxingSnippets.Templates boxingSnippets;
+    private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
 
     private final Map<Descriptor, HotSpotRuntimeCallTarget> runtimeCalls = new HashMap<>();
     private final Map<ResolvedJavaMethod, Stub> stubs = new HashMap<>();
@@ -223,25 +225,25 @@
                         /* arg0:     index */ javaCallingConvention(Kind.Int));
 
         addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Long));
 
         addRuntimeCall(JAVA_TIME_NANOS, config.javaTimeNanosStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Long));
 
         addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
@@ -277,7 +279,7 @@
      * @param ret where the call returns its result
      * @param args where arguments are passed to the call
      */
-    protected void addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) {
+    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) {
         Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length];
         for (int i = 0; i < temps.length; i++) {
             temps[i] = tempRegs[i].asValue();
@@ -290,6 +292,7 @@
         }
         HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM());
         runtimeCalls.put(descriptor, runtimeCall);
+        return runtimeCall;
     }
 
     private boolean checkAssignable(Class spec, Value value) {
@@ -303,67 +306,44 @@
         return kind == Kind.fromJavaClass(spec);
     }
 
-    /**
-     * Binds a snippet-base {@link Stub} to a runtime call descriptor.
-     * 
-     * @return the linkage information for a call to the stub
-     */
-    public HotSpotRuntimeCallTarget registerStub(Descriptor descriptor, Stub stub) {
-        HotSpotRuntimeCallTarget linkage = runtimeCalls.get(descriptor);
-        assert linkage != null;
-        linkage.setStub(stub);
-        stubs.put(stub.getMethod(), stub);
-        return linkage;
-    }
-
     protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig);
 
-    public void installReplacements(Backend backend, ReplacementsInstaller installer, Assumptions assumptions) {
+    public void registerReplacements(Replacements replacements) {
         if (GraalOptions.IntrinsifyObjectMethods) {
-            installer.installSubstitutions(ObjectSubstitutions.class);
+            replacements.registerSubstitutions(ObjectSubstitutions.class);
         }
         if (GraalOptions.IntrinsifySystemMethods) {
-            installer.installSubstitutions(SystemSubstitutions.class);
+            replacements.registerSubstitutions(SystemSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyThreadMethods) {
-            installer.installSubstitutions(ThreadSubstitutions.class);
+            replacements.registerSubstitutions(ThreadSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyUnsafeMethods) {
-            installer.installSubstitutions(UnsafeSubstitutions.class);
+            replacements.registerSubstitutions(UnsafeSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyClassMethods) {
-            installer.installSubstitutions(ClassSubstitutions.class);
+            replacements.registerSubstitutions(ClassSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyAESMethods) {
-            installer.installSubstitutions(AESCryptSubstitutions.class);
-            installer.installSubstitutions(CipherBlockChainingSubstitutions.class);
-        }
-        if (GraalOptions.IntrinsifyArrayCopy) {
-            installer.installSnippets(ArrayCopySnippets.class);
-        }
-        if (GraalOptions.IntrinsifyObjectClone) {
-            installer.installSnippets(ObjectCloneSnippets.class);
+            replacements.registerSubstitutions(AESCryptSubstitutions.class);
+            replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
 
-        installer.installSnippets(CheckCastSnippets.class);
-        installer.installSnippets(InstanceOfSnippets.class);
-        installer.installSnippets(NewObjectSnippets.class);
-        installer.installSnippets(MonitorSnippets.class);
-
-        installer.installSnippets(NewInstanceStub.class);
-        installer.installSnippets(NewArrayStub.class);
-        installer.installSnippets(WriteBarrierSnippets.class);
+        checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useTLAB);
+        monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useFastLocking);
+        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
 
-        checkcastSnippets = new CheckCastSnippets.Templates(this, assumptions, graalRuntime.getTarget());
-        instanceofSnippets = new InstanceOfSnippets.Templates(this, assumptions, graalRuntime.getTarget());
-        newObjectSnippets = new NewObjectSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useTLAB);
-        monitorSnippets = new MonitorSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useFastLocking);
-        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, assumptions, graalRuntime.getTarget());
+        registerStub(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE)));
+        registerStub(new NewArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_ARRAY)));
+    }
 
-        newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget());
-        newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget());
-        newInstanceStub.install(backend);
-        newArrayStub.install(backend);
+    private void registerStub(Stub stub) {
+        stub.getLinkage().setStub(stub);
+        stubs.put(stub.getMethod(), stub);
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
@@ -391,18 +371,18 @@
             addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
             RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
-            for (Safepoint safepoint : compResult.getSafepoints()) {
-                if (safepoint instanceof Call) {
-                    Call call = (Call) safepoint;
+            for (Infopoint infopoint : compResult.getInfopoints()) {
+                if (infopoint instanceof Call) {
+                    Call call = (Call) infopoint;
                     if (call.debugInfo != null) {
                         hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
                     }
                     addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}");
                 } else {
-                    if (safepoint.debugInfo != null) {
-                        hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString());
+                    if (infopoint.debugInfo != null) {
+                        hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
                     }
-                    addOperandComment(hcf, safepoint.pcOffset, "{safepoint}");
+                    addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
                 }
             }
             for (DataPatch site : compResult.getDataReferences()) {
@@ -496,15 +476,6 @@
         return regConfig;
     }
 
-    /**
-     * HotSpots needs an area suitable for storing a program counter for temporary use during the
-     * deoptimization process.
-     */
-    @Override
-    public int getCustomStackAreaSize() {
-        return graalRuntime.getTarget().wordSize;
-    }
-
     @Override
     public int getMinimumOutgoingSize() {
         return config.runtimeCallStackSize;
@@ -535,7 +506,7 @@
                 NodeInputList<ValueNode> parameters = callTarget.arguments();
                 ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
                 if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) {
-                    invoke.node().dependencies().add(tool.createNullCheckGuard(receiver));
+                    invoke.asNode().dependencies().add(tool.createNullCheckGuard(receiver));
                 }
                 JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
@@ -555,10 +526,10 @@
                             ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
                                             StampFactory.forKind(wordKind())));
 
-                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(),
+                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                             CallingConvention.Type.JavaCall));
 
-                            graph.addBeforeFixed(invoke.node(), hub);
+                            graph.addBeforeFixed(invoke.asNode(), hub);
                             graph.addAfterFixed(hub, metaspaceMethod);
                             graph.addAfterFixed(metaspaceMethod, compiledEntry);
                         }
@@ -566,7 +537,7 @@
                 }
 
                 if (loweredCallTarget == null) {
-                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
+                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
                                     callTarget.invokeKind()));
                 }
                 callTarget.replaceAndDelete(loweredCallTarget);
@@ -575,16 +546,11 @@
             LoadFieldNode loadField = (LoadFieldNode) n;
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
             ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object();
-            LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph);
             assert loadField.kind() != Kind.Illegal;
             ReadNode memoryRead = graph.add(new ReadNode(object, LocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp()));
             memoryRead.dependencies().add(tool.createNullCheckGuard(object));
 
             graph.replaceFixedWithFixed(loadField, memoryRead);
-            if (config.useG1GC && field.getKind() == Kind.Object && field.getDeclaringClass().getName().toString().equals("Ljava/lang/ref/Reference;") && field.getName().equals("referent")) {
-                WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryRead.object(), memoryRead, location, false));
-                graph.addAfterFixed(memoryRead, writeBarrierPre);
-            }
 
             if (loadField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
@@ -597,27 +563,14 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
             LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location));
+            WriteBarrierType barrierType = getFieldStoreBarrier(storeField);
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType));
             memoryWrite.dependencies().add(tool.createNullCheckGuard(object));
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
             FixedWithNextNode last = memoryWrite;
             FixedWithNextNode first = memoryWrite;
 
-            if (field.getKind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) {
-                if (config.useG1GC) {
-                    WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryWrite.object(), null, memoryWrite.location(), true));
-                    WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(memoryWrite.object(), memoryWrite.value(), memoryWrite.location(), false));
-                    graph.addBeforeFixed(memoryWrite, writeBarrierPre);
-                    graph.addAfterFixed(memoryWrite, writeBarrierPost);
-                    first = writeBarrierPre;
-                    last = writeBarrierPost;
-                } else {
-                    FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object()));
-                    graph.addAfterFixed(memoryWrite, writeBarrier);
-                    last = writeBarrier;
-                }
-            }
             if (storeField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
                 graph.addBeforeFixed(first, preMembar);
@@ -627,31 +580,7 @@
         } else if (n instanceof CompareAndSwapNode) {
             // 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, 1);
-            if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
-                ResolvedJavaType type = cas.object().objectStamp().type();
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true));
-                        WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, false));
-                        graph.addBeforeFixed(cas, writeBarrierPre);
-                        graph.addAfterFixed(cas, writeBarrierPost);
-                    } else {
-                        graph.addAfterFixed(cas, graph.add(new FieldWriteBarrier(cas.object())));
-                    }
-                } else {
-                    // This may be an array store so use an array write barrier
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true));
-                        graph.addBeforeFixed(cas, writeBarrierPre);
-                        graph.addAfterFixed(cas, graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, true)));
-                    } else {
-                        graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location)));
-                    }
-                }
-            }
+            cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
             ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool);
@@ -687,21 +616,12 @@
                     value = checkcast;
                 }
             }
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation));
+            WriteBarrierType barrierType = getArrayStoreBarrier(storeIndexed);
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType));
             memoryWrite.dependencies().add(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
-            if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
-                if (config.useG1GC) {
-                    WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(array, null, arrayLocation, true));
-                    graph.addBeforeFixed(memoryWrite, writeBarrierPre);
-                    WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(array, value, arrayLocation, true));
-                    graph.addAfterFixed(memoryWrite, writeBarrierPost);
-                } else {
-                    graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
-                }
-            }
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
@@ -715,32 +635,11 @@
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             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));
+            WriteBarrierType barrierType = getUnsafeStoreBarrier(store);
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
-            if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) {
-                ResolvedJavaType type = object.objectStamp().type();
-                // WriteBarrier writeBarrier;
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = new WriteBarrierPre(object, null, location, true);
-                        graph.addBeforeFixed(write, graph.add(writeBarrierPre));
-                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, false)));
-                    } else {
-                        graph.addAfterFixed(write, graph.add(new FieldWriteBarrier(object)));
-                    }
-                } else {
-                    // This may be an array store so use an array write barrier
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(object, null, location, true));
-                        graph.addBeforeFixed(write, writeBarrierPre);
-                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, true)));
-                    } else {
-                        graph.addAfterFixed(write, graph.add(new ArrayWriteBarrier(object, location)));
-                    }
-                }
-            }
+
         } else if (n instanceof LoadHubNode) {
             LoadHubNode loadHub = (LoadHubNode) n;
             assert loadHub.kind() == wordKind;
@@ -771,14 +670,10 @@
             monitorSnippets.lower((MonitorEnterNode) n, tool);
         } else if (n instanceof MonitorExitNode) {
             monitorSnippets.lower((MonitorExitNode) n, tool);
-        } else if (n instanceof FieldWriteBarrier) {
-            writeBarrierSnippets.lower((FieldWriteBarrier) n, tool);
-        } else if (n instanceof ArrayWriteBarrier) {
-            writeBarrierSnippets.lower((ArrayWriteBarrier) n, tool);
-        } else if (n instanceof WriteBarrierPre) {
-            writeBarrierSnippets.lower((WriteBarrierPre) n, tool);
-        } else if (n instanceof WriteBarrierPost) {
-            writeBarrierSnippets.lower((WriteBarrierPost) n, tool);
+        } else if (n instanceof SerialWriteBarrier) {
+            writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
+        } else if (n instanceof SerialArrayRangeWriteBarrier) {
+            writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
         } else if (n instanceof TLABAllocateNode) {
             newObjectSnippets.lower((TLABAllocateNode) n, tool);
         } else if (n instanceof InitializeObjectNode) {
@@ -787,17 +682,65 @@
             newObjectSnippets.lower((InitializeArrayNode) n, tool);
         } else if (n instanceof NewMultiArrayNode) {
             newObjectSnippets.lower((NewMultiArrayNode) n, tool);
+        } else if (n instanceof LoadExceptionObjectNode) {
+            exceptionObjectSnippets.lower((LoadExceptionObjectNode) n);
         } 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) {
+        } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) {
             // Nothing to do, using direct LIR lowering for these nodes.
+        } else if (n instanceof BoxNode) {
+            boxingSnippets.lower((BoxNode) n);
+        } else if (n instanceof UnboxNode) {
+            boxingSnippets.lower((UnboxNode) n);
         } else {
             assert false : "Node implementing Lowerable not handled: " + n;
             throw GraalInternalError.shouldNotReachHere();
         }
     }
 
+    private static WriteBarrierType getFieldStoreBarrier(StoreFieldNode storeField) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (storeField.field().getKind() == Kind.Object && !storeField.value().objectStamp().alwaysNull()) {
+            barrierType = WriteBarrierType.IMPRECISE;
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getArrayStoreBarrier(StoreIndexedNode store) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (store.elementKind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
+            barrierType = WriteBarrierType.PRECISE;
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getUnsafeStoreBarrier(UnsafeStoreNode store) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (store.value().kind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
+            ResolvedJavaType type = store.object().objectStamp().type();
+            if ((type != null && type.isArray() && !MetaUtil.isJavaLangObject(type))) {
+                barrierType = WriteBarrierType.PRECISE;
+            } else {
+                barrierType = WriteBarrierType.IMPRECISE;
+            }
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (cas.expected().kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
+            ResolvedJavaType type = cas.object().objectStamp().type();
+            if ((type != null && type.isArray() && !MetaUtil.isJavaLangObject(type))) {
+                barrierType = WriteBarrierType.PRECISE;
+            } else {
+                barrierType = WriteBarrierType.IMPRECISE;
+            }
+        }
+        return barrierType;
+    }
+
     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);
@@ -827,8 +770,10 @@
     }
 
     public HotSpotRuntimeCallTarget lookupRuntimeCall(Descriptor descriptor) {
-        assert runtimeCalls.containsKey(descriptor) : descriptor;
-        return runtimeCalls.get(descriptor);
+        HotSpotRuntimeCallTarget callTarget = runtimeCalls.get(descriptor);
+        assert runtimeCalls != null : descriptor;
+        callTarget.finalizeAddress(graalRuntime.getBackend());
+        return callTarget;
     }
 
     public ResolvedJavaMethod lookupJavaMethod(Method reflectionMethod) {
@@ -851,16 +796,21 @@
         return graalRuntime.getCompilerToVM().getJavaField(reflectionField);
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
-        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true);
+    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) {
+        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true);
         graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
         return installedCode;
     }
 
     @Override
     public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        return addMethod(method, compResult, null);
+    }
+
+    @Override
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false);
+        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false);
         CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
@@ -979,7 +929,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long nmethod = ((HotSpotInstalledCode) code).nmethod;
+            long nmethod = ((HotSpotInstalledCode) code).getMethodAddress();
             return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -60,6 +62,6 @@
      */
     @Override
     public String toString() {
-        return MetaUtil.format("%H.%n [unresolved]", this);
+        return format("HotSpotField<%H.%n %t, unresolved>", this);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +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.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class ArrayWriteBarrier extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-    @Input private LocationNode location;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public ArrayWriteBarrier(ValueNode object, LocationNode location) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.location = location;
-    }
-
-    public void lower(LoweringTool generator) {
-        generator.getRuntime().lower(this, generator);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -70,7 +70,6 @@
     @Override
     public void generate(LIRGenerator gen) {
         assert lockDepth != -1;
-        assert stateAfter() != null;
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         if (!eliminated) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode {
+
+    public DeoptimizingStubCall(Stamp stamp) {
+        super(stamp);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +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.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class FieldWriteBarrier extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public FieldWriteBarrier(ValueNode object) {
-        super(StampFactory.forVoid());
-        this.object = object;
-    }
-
-    public void lower(LoweringTool generator) {
-        generator.getRuntime().lower(this, generator);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,22 +24,24 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
 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.word.*;
+import com.oracle.graal.phases.common.*;
 
 public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable {
 
-    @Input private final ValueNode targetAddress;
-    @Input private final ValueNode metaspaceObject;
+    @Input private final ValueNode code;
     private final Class[] signature;
 
-    public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
+    public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
         super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3});
-        this.targetAddress = targetAddress;
-        this.metaspaceObject = metaspaceObject;
+        this.code = code;
         this.signature = signature;
     }
 
@@ -50,30 +52,57 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        replaceWithInvoke(tool);
+        if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) {
+            HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject();
+            InvokeNode invoke = replaceWithInvoke(tool.getRuntime());
+            StructuredGraph graph = (StructuredGraph) hsCode.getGraph();
+            if (graph != null) {
+                InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false);
+            }
+        } else {
+            replaceWithInvoke(tool.getRuntime());
+        }
     }
 
-    private InvokeNode replaceWithInvoke(LoweringTool tool) {
-        InvokeNode invoke = createInvoke(tool);
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke);
-        return invoke;
-    }
-
-    protected InvokeNode createInvoke(LoweringTool tool) {
+    protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) {
         ResolvedJavaMethod method = null;
+        ResolvedJavaField methodField = null;
+        ResolvedJavaField metaspaceMethodField = null;
+        ResolvedJavaField nmethodField = null;
         try {
-            method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw new IllegalStateException();
+            method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
+            methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method"));
+            nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod"));
+            metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod"));
+        } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) {
+            throw new IllegalStateException(e);
         }
         ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length];
         for (int i = 0; i < signature.length; i++) {
-            signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]);
+            signatureTypes[i] = tool.lookupJavaType(signature[i]);
         }
-        HotSpotIndirectCallTargetNode callTarget = graph().add(
-                        new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0));
+        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
+
+        StructuredGraph g = (StructuredGraph) graph();
+
+        LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField));
+        UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind));
+
+        LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField));
+        LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField));
+
+        HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
+
+        InvokeNode invoke = g.add(new InvokeNode(callTarget, 0));
+
         invoke.setStateAfter(stateAfter());
+        g.replaceFixedWithFixed(this, invoke);
+
+        g.addBeforeFixed(invoke, loadmetaspaceMethod);
+        g.addBeforeFixed(loadmetaspaceMethod, loadMethod);
+        g.addBeforeFixed(invoke, load);
+        g.addBeforeFixed(load, loadnmethod);
+
         return invoke;
     }
 
@@ -82,6 +111,6 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3);
+    public static native <T> T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3);
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,7 +34,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_identityhashcode} stub.
  */
-public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class IdentityHashCodeStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, int.class, Object.class);
@@ -47,7 +47,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(IdentityHashCodeStubCall.IDENTITY_HASHCODE);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -75,7 +74,7 @@
     public boolean fillContents() {
         // We fill contents when G1 GC is used since we want to record
         // the original field values prior to stores
-        return HotSpotSnippetUtils.useG1GC() ? true : fillContents;
+        return fillContents;
     }
 
     public boolean locked() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -57,7 +56,7 @@
     }
 
     public boolean fillContents() {
-        return HotSpotSnippetUtils.useG1GC() ? true : fillContents;
+        return fillContents;
     }
 
     public boolean locked() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorenter} stub.
  */
-public class MonitorEnterStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class MonitorEnterStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     @Input private final ValueNode lock;
@@ -48,7 +48,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorEnterStubCall.MONITORENTER);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.operand(lock));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.operand(lock));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorexit} stub.
  */
-public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable, MonitorReference {
+public class MonitorExitStubCall extends DeoptimizingStubCall implements LIRGenLowerable, MonitorReference {
 
     @Input private final ValueNode object;
     private int lockDepth;
@@ -60,7 +60,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(slot));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.emitLea(slot));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to the {@code new_array} stub.
  */
-public class NewArraySlowStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewArraySlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -62,7 +62,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_SLOW);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * A call to the {@link NewArrayStub}.
  */
-public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -63,7 +63,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to HotSpot's {@code new_instance} stub.
  */
-public class NewInstanceSlowStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewInstanceSlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -60,7 +60,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE_SLOW);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * A call to the {@link NewInstanceStub}.
  */
-public class NewInstanceStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -61,7 +61,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * Node implementing a call to HotSpot's {@code new_multi_array} stub.
  */
-public class NewMultiArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewMultiArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -65,7 +65,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NewMultiArrayStubCall.NEW_MULTI_ARRAY);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -69,7 +69,7 @@
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, false);
+        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, null);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,7 +37,7 @@
 /**
  * Node implementing a call to HotSpot's ThreadIsInterrupted stub.
  */
-public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class ThreadIsInterruptedStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode thread;
     @Input private final ValueNode clearIsInterrupted;
@@ -52,7 +52,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(thread), gen.operand(clearIsInterrupted));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(thread), gen.operand(clearIsInterrupted));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -28,7 +28,6 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
@@ -51,15 +50,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        String where;
-        try {
-            LIRFrameState state = gen.state();
-            BytecodePosition pos = state.topFrame;
-            where = "near or " + CodeUtil.append(new StringBuilder(100), pos).toString().replace(CodeUtil.NEW_LINE, CodeUtil.NEW_LINE + "\t");
-        } catch (Throwable t) {
-            // Report a less accurate location when debug info cannot be obtained
-            where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
-        }
+        String where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
 
         HotSpotRuntime runtime = (HotSpotRuntime) gen.getRuntime();
         Constant whereArg = Constant.forObject(runtime.registerGCRoot(where));
@@ -71,7 +62,7 @@
         }
 
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VMErrorNode.VM_ERROR);
-        gen.emitCall(stub, stub.getCallingConvention(), false, whereArg, formatArg, gen.operand(value));
+        gen.emitCall(stub, stub.getCallingConvention(), null, whereArg, formatArg, gen.operand(value));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * Node implementing a call to HotSpot's object pointer verification stub.
  */
-public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class VerifyOopStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, void.class, Object.class);
@@ -45,7 +45,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VerifyOopStubCall.VERIFY_OOP);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -48,7 +48,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPostStubCall.WBPOSTCALL);
-        gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(object), gen.operand(card));
+        gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(object), gen.operand(card));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Mon Apr 15 08:51:19 2013 +0200
@@ -45,7 +45,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPreStubCall.WBPRECALL);
-        gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(object));
+        gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(object));
     }
 
     @NodeIntrinsic
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.hotspot.phases;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+
+public class WriteBarrierAdditionPhase extends Phase {
+
+    public WriteBarrierAdditionPhase() {
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (WriteNode node : graph.getNodes(WriteNode.class)) {
+            addWriteNodeBarriers(node, graph);
+        }
+        for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
+            addCASBarriers(node, graph);
+        }
+        for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) {
+            addArrayRangeBarriers(node, graph);
+        }
+    }
+
+    private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
+        WriteBarrierType barrierType = node.getWriteBarrierType();
+        if (barrierType == WriteBarrierType.PRECISE) {
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true)));
+        } else if (barrierType == WriteBarrierType.IMPRECISE) {
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false)));
+        } else {
+            assert barrierType == WriteBarrierType.NONE;
+        }
+
+    }
+
+    private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) {
+        WriteBarrierType barrierType = node.getWriteBarrierType();
+        if (barrierType == WriteBarrierType.PRECISE) {
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, node.expected().kind(), node.displacement(), node.offset(), graph, 1);
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), location, true)));
+        } else if (barrierType == WriteBarrierType.IMPRECISE) {
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, node.expected().kind(), node.displacement(), node.offset(), graph, 1);
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), location, false)));
+        } else {
+            assert barrierType == WriteBarrierType.NONE;
+        }
+    }
+
+    private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) {
+        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength()));
+        graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier);
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -69,7 +69,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), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), ANY_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) {
@@ -98,7 +98,7 @@
         @Override
         public void generate(LIRGenerator gen) {
             RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(descriptor);
-            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key));
+            gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(in), gen.operand(out), gen.operand(key));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.replacements.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable {
@@ -60,7 +60,7 @@
         return arguments.get(4);
     }
 
-    private StructuredGraph selectSnippet(LoweringTool tool) {
+    private StructuredGraph selectSnippet(LoweringTool tool, Replacements replacements) {
         ResolvedJavaType srcType = getSource().objectStamp().type();
         ResolvedJavaType destType = getDestination().objectStamp().type();
 
@@ -72,7 +72,7 @@
         }
         Kind componentKind = srcType.getComponentType().getKind();
         ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
-        return (StructuredGraph) snippetMethod.getCompilerStorage().get(Snippet.class);
+        return replacements.getSnippet(snippetMethod);
     }
 
     private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) {
@@ -82,9 +82,10 @@
         }
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
-        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
-        new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
-        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions());
+        new CanonicalizerPhase().apply(snippetGraph, context);
+        new LoopFullUnrollPhase().apply(snippetGraph, context);
+        new CanonicalizerPhase().apply(snippetGraph, context);
     }
 
     @Override
@@ -93,12 +94,11 @@
             return null;
         }
 
-        StructuredGraph snippetGraph = selectSnippet(tool);
+        Replacements replacements = tool.getReplacements();
+        StructuredGraph snippetGraph = selectSnippet(tool, replacements);
         if (snippetGraph == null) {
             ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet);
-            snippetGraph = ((StructuredGraph) snippetMethod.getCompilerStorage().get(Snippet.class)).copy();
-            assert snippetGraph != null : "ArrayCopySnippets should be installed";
-
+            snippetGraph = replacements.getSnippet(snippetMethod).copy();
             replaceSnippetInvokes(snippetGraph);
         } else {
             assert snippetGraph != null : "ArrayCopySnippets should be installed";
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -75,7 +74,7 @@
     private static final Kind VECTOR_KIND = Kind.Long;
     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) {
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         checkNonNull(src);
         checkNonNull(dest);
         checkLimits(src, srcPos, dest, destPos, length);
@@ -236,9 +235,14 @@
         }
     }
 
+    @Snippet
+    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        arrayObjectCopy(src, srcPos, dest, destPos, length);
+    }
+
     // Does NOT perform store checks
     @Snippet
-    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+    public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
         checkNonNull(src);
         checkNonNull(dest);
@@ -260,15 +264,7 @@
             }
         }
         if (length > 0) {
-            int cardShift = cardTableShift();
-            long cardStart = cardTableStart();
-            long dstAddr = GetObjectAddressNode.get(dest);
-            long start = (dstAddr + header + (long) destPos * scale) >>> cardShift;
-            long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift;
-            long count = end - start + 1;
-            while (count-- > 0) {
-                DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
-            }
+            GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length);
         }
     }
 
@@ -278,14 +274,22 @@
         // loading the hubs also checks for nullness
         Word srcHub = loadHub(src);
         Word destHub = loadHub(dest);
+        int layoutHelper = checkArrayType(srcHub);
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
 
-        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);
+            if (isObjectArray) {
+                genericObjectExactCallCounter.inc();
+                probability(FAST_PATH_PROBABILITY);
+                arrayObjectCopy(src, srcPos, dest, destPos, length);
+            } else {
+                genericPrimitiveCallCounter.inc();
+                arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+            }
         } else {
             genericObjectCallCounter.inc();
             System.arraycopy(src, srcPos, dest, destPos, length);
@@ -308,34 +312,15 @@
         Word destNonVectorEnd = destStart.add(nonVectorBytes);
 
         while (destOffset.belowThan(destNonVectorEnd)) {
-            destOffset.writeByte(0, srcOffset.readByte(0, UNKNOWN_LOCATION), ANY_LOCATION);
+            destOffset.writeByte(0, srcOffset.readByte(0, ANY_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.writeWord(0, srcOffset.readWord(0, ANY_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);
-                }
-            }
-        }
     }
 
     private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+
+@ServiceProvider(ReplacementsProvider.class)
+public class CallSiteSubstitutions implements ReplacementsProvider {
+
+    @Override
+    public void registerReplacements(Replacements replacements) {
+        if (GraalOptions.IntrinsifyCallSiteTarget) {
+            replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
+            replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
+            replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
+        }
+    }
+
+    @ClassSubstitution(ConstantCallSite.class)
+    private static class ConstantCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(ConstantCallSite callSite);
+    }
+
+    @ClassSubstitution(MutableCallSite.class)
+    private static class MutableCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(MutableCallSite callSite);
+    }
+
+    @ClassSubstitution(VolatileCallSite.class)
+    private static class VolatileCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(VolatileCallSite callSite);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+public class CallSiteTargetNode extends MacroNode implements Canonicalizable, Lowerable {
+
+    public CallSiteTargetNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    private ValueNode getCallSite() {
+        return arguments.get(0);
+    }
+
+    private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccessProvider, Assumptions assumptions) {
+        if (getCallSite().isConstant() && !getCallSite().isNullConstant()) {
+            CallSite callSite = (CallSite) getCallSite().asConstant().asObject();
+            if (callSite instanceof ConstantCallSite) {
+                return ConstantNode.forObject(callSite.getTarget(), metaAccessProvider, graph());
+            } else if (callSite instanceof MutableCallSite || callSite instanceof VolatileCallSite && assumptions != null && assumptions.useOptimisticAssumptions()) {
+                MethodHandle target = callSite.getTarget();
+                assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
+                return ConstantNode.forObject(target, metaAccessProvider, graph());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        ConstantNode target = getConstantCallTarget(tool.runtime(), tool.assumptions());
+        if (target != null) {
+            return target;
+        }
+
+        return this;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions());
+
+        if (target != null) {
+            graph.replaceFixedWithFloating(this, target);
+        } else {
+            graph.replaceFixedWithFixed(this, createInvoke());
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -28,11 +28,9 @@
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
@@ -42,7 +40,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -58,16 +60,11 @@
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word hub, Word objectHub);
 
-    // @formatter:off
-
     /**
      * Type test used when the type being tested against is a final type.
      */
     @Snippet
-    public static Object checkcastExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -76,30 +73,25 @@
             if (objectHub.notEqual(exactHub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 exactMiss.inc();
-                //bkpt(object, exactHub, objectHub);
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
             exactHit.inc();
         }
-        /* make sure that the unsafeCast is done *after* the check above,
-         * cf. ReadAfterCheckCast */
+        /*
+         * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast
+         */
         BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     /**
      * Type test used when the type being tested against is a restricted primary type.
-     *
-     * This test ignores use of hints altogether as the display-based type check only
-     * involves one extra load where the second load should hit the same cache line as the
-     * first.
+     * 
+     * This test ignores use of hints altogether as the display-based type check only involves one
+     * extra load where the second load should hit the same cache line as the first.
      */
     @Snippet
-    public static Object checkcastPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -120,11 +112,7 @@
      * Type test used when the type being tested against is a restricted secondary type.
      */
     @Snippet
-    public static Object checkcastSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @VarargsParameter("hints") Word[] hints,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -149,14 +137,11 @@
     }
 
     /**
-     * Type test used when the type being tested against is not known at compile time (e.g. the type test
-     * in an object array store check).
+     * Type test used when the type being tested against is not known at compile time (e.g. the type
+     * test in an object array store check).
      */
     @Snippet
-    public static Object checkcastDynamic(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -170,21 +155,15 @@
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<CheckCastSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod exact;
-        private final ResolvedJavaMethod primary;
-        private final ResolvedJavaMethod secondary;
-        private final ResolvedJavaMethod dynamic;
+        private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact");
+        private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary");
+        private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary");
+        private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic");
 
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
-            super(runtime, assumptions, target, CheckCastSnippets.class);
-            exact = snippet("checkcastExact", Object.class, Word.class, boolean.class);
-            primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class);
-            secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class);
-            dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class);
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
         }
 
         /**
@@ -193,31 +172,34 @@
         public void lower(CheckCastNode checkcast, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
             ValueNode object = checkcast.object();
-            final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
             TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
             ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph());
-            boolean checkNull = !object.stamp().nonNull();
-            Arguments arguments;
-            Key key;
 
-            assert type != null;
+            Arguments args;
             if (hintInfo.exact) {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
                 assert hints.length == 1;
-                key = new Key(exact).add("checkNull", checkNull);
-                arguments = arguments("object", object).add("exactHub", hints[0]);
+                args = new Arguments(exact);
+                args.add("object", object);
+                args.add("exactHub", hints[0]);
             } else if (type.isPrimaryType()) {
-                key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                arguments = arguments("hub", hub).add("object", object);
+                args = new Arguments(primary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addConst("superCheckOffset", type.superCheckOffset());
             } else {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
-                key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
-                arguments = arguments("hub", hub).add("object", object).add("hints", hints);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
+                args = new Arguments(secondary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints);
             }
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
 
         /**
@@ -225,16 +207,16 @@
          */
         public void lower(CheckCastDynamicNode checkcast) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
-            ValueNode hub = checkcast.type();
             ValueNode object = checkcast.object();
-            boolean checkNull = !object.stamp().nonNull();
 
-            Key key = new Key(dynamic).add("checkNull", checkNull);
-            Arguments arguments = arguments("hub", hub).add("object", object);
+            Arguments args = new Arguments(dynamic);
+            args.add("hub", checkcast.type());
+            args.add("object", object);
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -65,7 +65,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), UNKNOWN_LOCATION);
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -74,8 +74,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), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_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) {
@@ -88,7 +88,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), UNKNOWN_LOCATION);
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -119,7 +119,7 @@
         @Override
         public void generate(LIRGenerator gen) {
             RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(descriptor);
-            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+            gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeIntrinsics.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeIntrinsics.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,16 +23,16 @@
 package com.oracle.graal.hotspot.replacements;
 
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.*;
 
 @ServiceProvider(ReplacementsProvider.class)
 public class HotSpotInstalledCodeIntrinsics implements ReplacementsProvider {
 
     @Override
-    public void installReplacements(ReplacementsInstaller installer) {
+    public void registerReplacements(Replacements replacements) {
         if (GraalOptions.IntrinsifyInstalledCodeMethods) {
-            installer.installSubstitutions(HotSpotInstalledCodeSubstitutions.class);
+            replacements.registerSubstitutions(HotSpotInstalledCodeSubstitutions.class);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,20 +27,18 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.word.*;
 
 @ClassSubstitution(HotSpotInstalledCode.class)
 public class HotSpotInstalledCodeSubstitutions {
 
-    @MethodSubstitution
-    public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) {
-        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
-        final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset);
-        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3);
+    @MethodSubstitution(isStatic = false)
+    public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) {
+        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3);
     }
 
     @Fold
     private static Class[] getSignature() {
         return new Class[]{Object.class, Object.class, Object.class};
     }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Mon Apr 15 08:51:19 2013 +0200
@@ -46,7 +46,6 @@
 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() {
@@ -63,6 +62,20 @@
         return config().verifyOops;
     }
 
+    public static final Object EXCEPTION_OOP_LOCATION = LocationNode.createLocation("ExceptionOop");
+
+    @Fold
+    public static int threadExceptionOopOffset() {
+        return config().threadExceptionOopOffset;
+    }
+
+    public static final Object EXCEPTION_PC_LOCATION = LocationNode.createLocation("ExceptionPc");
+
+    @Fold
+    public static int threadExceptionPcOffset() {
+        return config().threadExceptionPcOffset;
+    }
+
     public static final Object TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop");
 
     @Fold
@@ -84,6 +97,18 @@
         return config().threadTlabStartOffset;
     }
 
+    public static Object readExceptionOop(Word thread) {
+        return thread.readObject(threadExceptionOopOffset(), EXCEPTION_OOP_LOCATION);
+    }
+
+    public static void writeExceptionOop(Word thread, Object value) {
+        thread.writeObject(threadExceptionOopOffset(), value, EXCEPTION_OOP_LOCATION);
+    }
+
+    public static void writeExceptionPc(Word thread, Word value) {
+        thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION);
+    }
+
     public static Word readTlabTop(Word thread) {
         return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,20 +24,22 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
 import com.oracle.graal.nodes.*;
 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.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -51,18 +53,11 @@
  */
 public class InstanceOfSnippets implements Snippets {
 
-    // @formatter:off
-
     /**
      * A test against a final type.
      */
     @Snippet
-    public static Object instanceofExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -82,13 +77,7 @@
      * A test against a primary type.
      */
     @Snippet
-    public static Object instanceofPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -108,13 +97,8 @@
      * A test against a restricted secondary type type.
      */
     @Snippet
-    public static Object instanceofSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @VarargsParameter("hints") Word[] hints,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
+                    @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -125,10 +109,11 @@
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < hints.length; i++) {
             Word hintHub = hints[i];
+            boolean positive = hintIsPositive[i];
             if (hintHub.equal(objectHub)) {
                 probability(NOT_FREQUENT_PROBABILITY);
                 hintsHit.inc();
-                return trueValue;
+                return positive ? trueValue : falseValue;
             }
         }
         if (!checkSecondarySubType(hub, objectHub)) {
@@ -141,12 +126,7 @@
      * Type test used when the type being tested against is not known at compile time.
      */
     @Snippet
-    public static Object instanceofDynamic(
-                    @Parameter("mirror") Class mirror,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -161,61 +141,63 @@
         return trueValue;
     }
 
-    // @formatter:on
-
-    public static class Templates extends InstanceOfSnippetsTemplates<InstanceOfSnippets> {
+    public static class Templates extends InstanceOfSnippetsTemplates {
 
-        private final ResolvedJavaMethod instanceofExact;
-        private final ResolvedJavaMethod instanceofPrimary;
-        private final ResolvedJavaMethod instanceofSecondary;
-        private final ResolvedJavaMethod instanceofDynamic;
+        private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact");
+        private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
+        private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
+        private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
 
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
-            super(runtime, assumptions, target, InstanceOfSnippets.class);
-            instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class);
-            instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class);
-            instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean.class);
-            instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class);
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
         }
 
         @Override
-        protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
+        protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
                 TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
-                boolean checkNull = !object.stamp().nonNull();
-                Arguments arguments;
-                Key key;
+
+                Arguments args;
                 if (hintInfo.exact) {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+                    ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
                     assert hints.length == 1;
-                    key = new Key(instanceofExact).add("checkNull", checkNull);
-                    arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofExact);
+                    args.add("object", object);
+                    args.add("exactHub", hints[0]);
                 } else if (type.isPrimaryType()) {
-                    key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                    arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofPrimary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
-                    key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
-                    arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue);
+                    Hints hints = createHints(hintInfo, runtime, false, hub.graph());
+                    args = new Arguments(instanceofSecondary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
+                    args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
-                return new KeyAndArguments(key, arguments);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
+
             } else {
                 assert replacer.instanceOf instanceof InstanceOfDynamicNode;
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
-                ValueNode mirror = instanceOf.mirror();
-                boolean checkNull = !object.stamp().nonNull();
-                Key key = new Key(instanceofDynamic).add("checkNull", checkNull);
-                Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
-                return new KeyAndArguments(key, arguments);
+
+                Arguments args = new Arguments(instanceofDynamic);
+                args.add("mirror", instanceOf.mirror());
+                args.add("object", object);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.replacements;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
+import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.word.*;
+
+/**
+ * Snippet for loading the exception object at the start of an exception dispatcher.
+ */
+public class LoadExceptionObjectSnippets implements Snippets {
+
+    @Snippet
+    public static Object loadException() {
+        Word thread = thread();
+        Object exception = readExceptionOop(thread);
+        writeExceptionOop(thread, null);
+        writeExceptionPc(thread, Word.zero());
+        return unsafeCast(exception, StampFactory.forNodeIntrinsic());
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException");
+
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+        }
+
+        public void lower(LoadExceptionObjectNode loadExceptionObject) {
+            Arguments args = new Arguments(loadException);
+            template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}.
+ */
+public class MethodHandleInvokeBasicNode extends MacroNode {
+
+    public MethodHandleInvokeBasicNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}.
+ */
+public class MethodHandleLinkToInterfaceNode extends MacroNode {
+
+    public MethodHandleLinkToInterfaceNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}.
+ */
+public class MethodHandleLinkToSpecialNode extends MacroNode {
+
+    public MethodHandleLinkToSpecialNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}.
+ */
+public class MethodHandleLinkToStaticNode extends MacroNode {
+
+    public MethodHandleLinkToStaticNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}.
+ */
+public class MethodHandleLinkToVirtualNode extends MacroNode {
+
+    public MethodHandleLinkToVirtualNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -46,7 +46,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -73,7 +76,7 @@
     public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
-    public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
 
         if (checkNull && object == null) {
@@ -262,7 +265,7 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
         incCounter();
         if (checkNull && object == null) {
@@ -276,7 +279,7 @@
     }
 
     @Snippet
-    public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexit(Object object, @ConstantParameter boolean trace) {
         trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
         if (useBiasedLocking()) {
             // Check for biased locking unlock case, which is a no-op
@@ -328,7 +331,7 @@
      * Calls straight out to the monitorexit stub.
      */
     @Snippet
-    public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexitStub(Object object, @ConstantParameter boolean trace) {
         verifyOop(object);
         traceObject(trace, "-lock{stub}", object);
         MonitorExitStubCall.call(object);
@@ -398,54 +401,45 @@
         }
     }
 
-    public static class Templates extends AbstractTemplates<MonitorSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod monitorenter;
-        private final ResolvedJavaMethod monitorexit;
-        private final ResolvedJavaMethod monitorenterStub;
-        private final ResolvedJavaMethod monitorexitStub;
-        private final ResolvedJavaMethod monitorenterEliminated;
-        private final ResolvedJavaMethod monitorexitEliminated;
-        private final ResolvedJavaMethod initCounter;
-        private final ResolvedJavaMethod checkCounter;
+        private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter");
+        private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit");
+        private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub");
+        private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub");
+        private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated");
+        private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated");
+        private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter");
+        private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter");
+
         private final boolean useFastLocking;
 
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target, boolean useFastLocking) {
-            super(runtime, assumptions, target, MonitorSnippets.class);
-            monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class);
-            monitorexit = snippet("monitorexit", Object.class, boolean.class);
-            monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class);
-            monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class);
-            monitorenterEliminated = snippet("monitorenterEliminated");
-            monitorexitEliminated = snippet("monitorexitEliminated");
-            initCounter = snippet("initCounter");
-            checkCounter = snippet("checkCounter", String.class);
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) {
+            super(runtime, replacements, target);
             this.useFastLocking = useFastLocking;
         }
 
         public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorenterNode.graph();
-
             checkBalancedMonitors(graph);
-
             FrameState stateAfter = monitorenterNode.stateAfter();
-            boolean eliminated = monitorenterNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub;
-            boolean checkNull = !monitorenterNode.object().stamp().nonNull();
-            Key key = new Key(method);
-            if (method != monitorenterEliminated) {
-                key.add("checkNull", checkNull);
-            }
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorenterNode.eliminated()) {
+                args = new Arguments(monitorenterEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorenter);
+                } else {
+                    args = new Arguments(monitorenterStub);
+                }
+                args.add("object", monitorenterNode.object());
+                args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull());
+                args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
 
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorenterNode.object());
-            }
-            SnippetTemplate template = cache.get(key, assumptions);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments);
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof BeginLockScopeNode) {
                     BeginLockScopeNode begin = (BeginLockScopeNode) n;
@@ -460,18 +454,22 @@
         public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorexitNode.graph();
             FrameState stateAfter = monitorexitNode.stateAfter();
-            boolean eliminated = monitorexitNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub;
-            Key key = new Key(method);
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorexitNode.eliminated()) {
+                args = new Arguments(monitorexitEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorexit);
+                } else {
+                    args = new Arguments(monitorexitStub);
+                }
+                args.add("object", monitorexitNode.object());
+                args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorexitNode.object());
-            }
-            SnippetTemplate template = cache.get(key, assumptions);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments);
+
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof EndLockScopeNode) {
                     EndLockScopeNode end = (EndLockScopeNode) n;
@@ -521,26 +519,27 @@
                 NodeIterable<MonitorCounterNode> nodes = graph.getNodes().filter(MonitorCounterNode.class);
                 if (nodes.isEmpty()) {
                     // Only insert the nodes if this is the first monitorenter being lowered.
-                    JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass());
-                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType));
+                    JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass());
+                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType));
                     InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0));
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
-                    StructuredGraph inlineeGraph = (StructuredGraph) initCounter.getCompilerStorage().get(Snippet.class);
+
+                    StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod());
                     InliningUtil.inline(invoke, inlineeGraph, false);
 
                     List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
-                        returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass());
+                        returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d");
                         ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph);
-                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType));
+                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0));
                         List<ValueNode> stack = Collections.emptyList();
                         FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false);
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
-                        inlineeGraph = (StructuredGraph) checkCounter.getCompilerStorage().get(Snippet.class);
+                        inlineeGraph = replacements.getSnippet(checkCounter.getMethod());
                         InliningUtil.inline(invoke, inlineeGraph, false);
                     }
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,9 +26,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
-import static com.oracle.graal.replacements.Snippet.Varargs.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
 
@@ -43,7 +41,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -52,15 +54,16 @@
  */
 public class NewObjectSnippets implements Snippets {
 
-    // @formatter:off
-
     @Snippet
-    public static Word allocate(@Parameter("size") int size) {
+    public static Word allocate(int size) {
         Word thread = thread();
         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)
+        /*
+         * 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);
             writeTlabTop(thread, newTop);
@@ -70,13 +73,7 @@
     }
 
     @Snippet
-    public static Object initializeObject(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("size") int size,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) {
 
         Object result;
         if (memory.equal(0)) {
@@ -91,19 +88,17 @@
             }
             result = memory.toObject();
         }
-        return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic());
+        /*
+         * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast
+         * and CheckCastSnippets
+         */
+        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     @Snippet
-    public static Object initializeArray(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("length") int length,
-                    @Parameter("allocationSize") int allocationSize,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean locked) {
         if (locked) {
             return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents);
         } else {
@@ -122,7 +117,8 @@
             formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents);
             result = memory.toObject();
         }
-        return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     /**
@@ -131,13 +127,8 @@
     public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
 
     @Snippet
-    public static Object allocateArrayAndInitialize(
-                    @Parameter("length") int length,
-                    @ConstantParameter("alignment") int alignment,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("log2ElementSize") int log2ElementSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("type") ResolvedJavaType type) {
+    public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
+                    @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) {
         if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
             probability(DEOPT_PATH_PROBABILITY);
             // This handles both negative array sizes and very large array sizes
@@ -149,9 +140,10 @@
     }
 
     /**
-     * Computes the size of the memory chunk allocated for an array. This size accounts for the array
-     * header size, boy size and any padding after the last element to satisfy object alignment requirements.
-     *
+     * Computes the size of the memory chunk allocated for an array. This size accounts for the
+     * array header size, boy size and any padding after the last element to satisfy object
+     * alignment requirements.
+     * 
      * @param length the number of elements in the array
      * @param alignment the object alignment requirement
      * @param headerSize the size of the array header
@@ -167,10 +159,7 @@
      * Calls the runtime stub for implementing MULTIANEWARRAY.
      */
     @Snippet
-    public static Object newmultiarray(
-                    @Parameter("hub") Word hub,
-                    @ConstantParameter("rank") int rank,
-                    @VarargsParameter("dimensions") int[] dimensions) {
+    public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
@@ -180,9 +169,8 @@
     }
 
     /**
-     * Maximum size of an object whose body is initialized by a sequence of
-     * zero-stores to its fields. Larger objects have their bodies initialized
-     * in a loop.
+     * Maximum size of an object whose body is initialized by a sequence of zero-stores to its
+     * fields. Larger objects have their bodies initialized in a loop.
      */
     private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize();
 
@@ -213,7 +201,10 @@
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
         memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION);
-        // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
+        /*
+         * store hub last as the concurrent garbage collectors assume length is valid if hub field
+         * is not null
+         */
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
@@ -222,27 +213,19 @@
         }
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<NewObjectSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod allocate;
-        private final ResolvedJavaMethod initializeObject;
-        private final ResolvedJavaMethod initializeArray;
-        private final ResolvedJavaMethod allocateArrayAndInitialize;
-        private final ResolvedJavaMethod newmultiarray;
-        private final TargetDescription target;
+        private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate");
+        private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject");
+        private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray");
+        private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize");
+        private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
+
         private final boolean useTLAB;
 
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target, boolean useTLAB) {
-            super(runtime, assumptions, target, NewObjectSnippets.class);
-            this.target = target;
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) {
+            super(runtime, replacements, target);
             this.useTLAB = useTLAB;
-            allocate = snippet("allocate", int.class);
-            initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class);
-            initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class);
-            allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class);
-            newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class);
         }
 
         /**
@@ -285,9 +268,10 @@
             int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind));
             if (!useTLAB) {
                 ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph);
-                // value for 'size' doesn't matter as it isn't used since a stub call will be made
-                // anyway
-                // for both allocation and initialization - it just needs to be non-null
+                /*
+                 * value for 'size' doesn't matter as it isn't used since a stub call will be made
+                 * anyway for both allocation and initialization - it just needs to be non-null
+                 */
                 ConstantNode size = ConstantNode.forInt(-1, graph);
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
@@ -300,12 +284,17 @@
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
             } else {
-                Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents",
-                                newArrayNode.fillContents()).add("type", arrayType);
-                Arguments arguments = new Arguments().add("length", lengthNode);
-                SnippetTemplate template = cache.get(key, assumptions);
-                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments);
-                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments);
+                Arguments args = new Arguments(allocateArrayAndInitialize);
+                args.add("length", lengthNode);
+                args.addConst("alignment", alignment);
+                args.addConst("headerSize", headerSize);
+                args.addConst("log2ElementSize", log2ElementSize);
+                args.addConst("fillContents", newArrayNode.fillContents());
+                args.addConst("type", arrayType);
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
+                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
             }
         }
 
@@ -313,11 +302,11 @@
         public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
             ValueNode size = tlabAllocateNode.size();
-            Key key = new Key(allocate);
-            Arguments arguments = arguments("size", size);
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments);
-            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(allocate).add("size", size);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args);
+            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -327,12 +316,18 @@
             assert !type.isArray();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             int size = instanceSize(type);
-            Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord());
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeObject);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("size", size).addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -344,13 +339,21 @@
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             Kind elementKind = elementType.getKind();
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
-            Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length",
-                            initializeNode.length());
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeArray);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("length", initializeNode.length());
+            args.add("allocationSize", initializeNode.allocationSize());
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("headerSize", headerSize);
+            args.addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -363,10 +366,12 @@
             }
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
-            Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank);
-            Arguments arguments = arguments("dimensions", dims).add("hub", hub);
-            SnippetTemplate template = cache.get(key, assumptions);
-            template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(newmultiarray);
+            args.add("hub", hub);
+            args.addConst("rank", rank);
+            args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims);
+            template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args);
         }
 
         private static int instanceSize(HotSpotResolvedObjectType type) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
@@ -70,7 +69,8 @@
             method = ObjectCloneSnippets.instanceCloneMethod;
         }
         ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method);
-        StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Snippet.class);
+        Replacements replacements = tool.getReplacements();
+        StructuredGraph snippetGraph = replacements.getSnippet(snippetMethod);
 
         assert snippetGraph != null : "ObjectCloneSnippets should be installed";
         return snippetGraph;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -58,7 +58,7 @@
 
         memory = Word.fromObject(result);
         for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION);
         }
 
         return result;
@@ -76,7 +76,7 @@
 
         memory = Word.fromObject(result);
         for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION);
         }
         return result;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.replacements.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.replacements.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * Substitutions for {@link java.lang.System} methods.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -45,7 +45,7 @@
         Object thread = javaThread.readObject(threadObjectOffset(), FINAL_LOCATION);
         if (thisObject == thread) {
             Word osThread = javaThread.readWord(osThreadOffset(), FINAL_LOCATION);
-            boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION) != 0;
+            boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), ANY_LOCATION) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,6 +25,8 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -98,12 +100,45 @@
         return false;
     }
 
-    static ConstantNode[] createHints(TypeCheckHints hints, MetaAccessProvider runtime, Graph graph) {
-        ConstantNode[] hintHubs = new ConstantNode[hints.types.length];
-        for (int i = 0; i < hintHubs.length; i++) {
-            hintHubs[i] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.types[i]).klass(), runtime, graph);
+    /**
+     * A set of type check hints ordered by decreasing probabilities.
+     */
+    public static class Hints {
+
+        /**
+         * The hubs of the hint types.
+         */
+        public final ConstantNode[] hubs;
+
+        /**
+         * A predicate over {@link #hubs} specifying whether the corresponding hint type is a
+         * sub-type of the checked type.
+         */
+        public final boolean[] isPositive;
+
+        Hints(ConstantNode[] hints, boolean[] hintIsPositive) {
+            this.hubs = hints;
+            this.isPositive = hintIsPositive;
         }
-        return hintHubs;
+    }
+
+    static Hints createHints(TypeCheckHints hints, MetaAccessProvider runtime, boolean positiveOnly, Graph graph) {
+        ConstantNode[] hubs = new ConstantNode[hints.hints.length];
+        boolean[] isPositive = new boolean[hints.hints.length];
+        int index = 0;
+        for (int i = 0; i < hubs.length; i++) {
+            if (!positiveOnly || hints.hints[i].positive) {
+                hubs[index] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.hints[i].type).klass(), runtime, graph);
+                isPositive[index] = hints.hints[i].positive;
+                index++;
+            }
+        }
+        if (positiveOnly && index != hubs.length) {
+            assert index < hubs.length;
+            hubs = Arrays.copyOf(hubs, index);
+            isPositive = Arrays.copyOf(isPositive, index);
+        }
+        return new Hints(hubs, isPositive);
     }
 
     static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -28,100 +28,27 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
-import com.oracle.graal.replacements.Snippet.Parameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
 public class WriteBarrierSnippets implements Snippets {
 
     @Snippet
-    public static void g1PreWriteBarrier(@Parameter("object") Object obj, @Parameter("expectedObject") Object expobj, @Parameter("location") Object location,
-                    @ConstantParameter("doLoad") boolean doLoad) {
-        Word thread = thread();
+    public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) {
         Object object = FixedValueAnchorNode.getObject(obj);
-        Object expectedObject = FixedValueAnchorNode.getObject(expobj);
-        Word field = (Word) Word.fromArray(object, location);
-        Word previousOop = (Word) Word.fromObject(expectedObject);
-        byte markingValue = thread.readByte(HotSpotSnippetUtils.g1SATBQueueMarkingOffset());
-
-        Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1SATBQueueBufferOffset());
-        Word indexAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueIndexOffset());
-        Word indexValue = indexAddress.readWord(0);
-
-        if (markingValue != (byte) 0) {
-            if (doLoad) {
-                previousOop = field.readWord(0);
-            }
-            if (previousOop.notEqual(Word.zero())) {
-                if (indexValue.notEqual(Word.zero())) {
-                    Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize());
-                    Word logAddress = bufferAddress.add(nextIndex);
-                    logAddress.writeWord(0, previousOop);
-                    indexAddress.writeWord(0, nextIndex);
-                } else {
-                    WriteBarrierPreStubCall.call(previousOop);
-
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static void g1PostWriteBarrier(@Parameter("object") Object obj, @Parameter("value") Object value, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) {
-        Word thread = thread();
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Object wrObject = FixedValueAnchorNode.getObject(value);
-        Word oop = (Word) Word.fromObject(object);
-        Word field;
+        Pointer oop;
         if (usePrecise) {
-            field = (Word) Word.fromArray(object, location);
+            oop = Word.fromArray(object, location);
         } else {
-            field = oop;
-        }
-        Word writtenValue = (Word) Word.fromObject(wrObject);
-        Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1CardQueueBufferOffset());
-        Word indexAddress = thread.add(HotSpotSnippetUtils.g1CardQueueIndexOffset());
-        Word indexValue = thread.readWord(HotSpotSnippetUtils.g1CardQueueIndexOffset());
-        Word xorResult = (field.xor(writtenValue)).unsignedShiftRight(HotSpotSnippetUtils.logOfHRGrainBytes());
-
-        // Card Table
-        Word cardBase = field.unsignedShiftRight(cardTableShift());
-        long startAddress = cardTableStart();
-        int displacement = 0;
-        if (((int) startAddress) == startAddress) {
-            displacement = (int) startAddress;
-        } else {
-            cardBase = cardBase.add(Word.unsigned(cardTableStart()));
+            oop = Word.fromObject(object);
         }
-        Word cardAddress = cardBase.add(displacement);
-
-        if (xorResult.notEqual(Word.zero())) {
-            if (writtenValue.notEqual(Word.zero())) {
-                byte cardByte = cardAddress.readByte(0);
-                if (cardByte != (byte) 0) {
-                    cardAddress.writeByte(0, (byte) 0); // smash zero into card
-                    if (indexValue.notEqual(Word.zero())) {
-                        Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize());
-                        Word logAddress = bufferAddress.add(nextIndex);
-                        logAddress.writeWord(0, cardAddress);
-                        indexAddress.writeWord(0, nextIndex);
-                    } else {
-                        WriteBarrierPostStubCall.call(object, cardAddress);
-                    }
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static void serialFieldWriteBarrier(@Parameter("object") Object obj) {
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Pointer oop = Word.fromObject(object);
         Word base = (Word) oop.unsignedShiftRight(cardTableShift());
         long startAddress = cardTableStart();
         int displacement = 0;
@@ -134,77 +61,44 @@
     }
 
     @Snippet
-    public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location) {
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Pointer oop = Word.fromArray(object, location);
-        Word base = (Word) oop.unsignedShiftRight(cardTableShift());
-        long startAddress = cardTableStart();
-        int displacement = 0;
-        if (((int) startAddress) == startAddress) {
-            displacement = (int) startAddress;
-        } else {
-            base = base.add(Word.unsigned(cardTableStart()));
+    public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) {
+        Object dest = FixedValueAnchorNode.getObject(object);
+        int cardShift = cardTableShift();
+        long cardStart = cardTableStart();
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+        long dstAddr = GetObjectAddressNode.get(dest);
+        long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift;
+        long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift;
+        long count = end - start + 1;
+        while (count-- > 0) {
+            DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
         }
-        base.writeByte(displacement, (byte) 0);
     }
 
-    public static class Templates extends AbstractTemplates<WriteBarrierSnippets> {
-
-        private final ResolvedJavaMethod serialFieldWriteBarrier;
-        private final ResolvedJavaMethod serialArrayWriteBarrier;
-        private final ResolvedJavaMethod g1PreWriteBarrier;
-        private final ResolvedJavaMethod g1PostWriteBarrier;
+    public static class Templates extends AbstractTemplates {
 
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
-            super(runtime, assumptions, target, WriteBarrierSnippets.class);
-            serialFieldWriteBarrier = snippet("serialFieldWriteBarrier", Object.class);
-            serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class);
-            g1PreWriteBarrier = snippet("g1PreWriteBarrier", Object.class, Object.class, Object.class, boolean.class);
-            g1PostWriteBarrier = snippet("g1PostWriteBarrier", Object.class, Object.class, Object.class, boolean.class);
+        private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier");
+        private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
+
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
         }
 
-        public void lower(ArrayWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialArrayWriteBarrier;
-            Key key = new Key(method);
-            Arguments arguments = new Arguments();
-            arguments.add("object", arrayWriteBarrier.getObject());
-            arguments.add("location", arrayWriteBarrier.getLocation());
-            SnippetTemplate template = cache.get(key, assumptions);
-            template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments);
-        }
-
-        public void lower(FieldWriteBarrier fieldWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialFieldWriteBarrier;
-            Key key = new Key(method);
-            Arguments arguments = new Arguments();
-            arguments.add("object", fieldWriteBarrier.getObject());
-            SnippetTemplate template = cache.get(key, assumptions);
-            template.instantiate(runtime, fieldWriteBarrier, DEFAULT_REPLACER, arguments);
+        public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(serialArrayWriteBarrier);
+            args.add("obj", arrayWriteBarrier.getObject());
+            args.add("location", arrayWriteBarrier.getLocation());
+            args.addConst("usePrecise", arrayWriteBarrier.usePrecise());
+            template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args);
         }
 
-        public void lower(WriteBarrierPre writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = g1PreWriteBarrier;
-            Key key = new Key(method);
-            key.add("doLoad", writeBarrierPre.doLoad());
-            Arguments arguments = new Arguments();
-            arguments.add("object", writeBarrierPre.getObject());
-            arguments.add("expectedObject", writeBarrierPre.getExpectedObject());
-            arguments.add("location", writeBarrierPre.getLocation());
-            SnippetTemplate template = cache.get(key, assumptions);
-            template.instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, arguments);
+        public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(serialArrayRangeWriteBarrier);
+            args.add("object", arrayRangeWriteBarrier.getObject());
+            args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+            args.add("length", arrayRangeWriteBarrier.getLength());
+            template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
-
-        public void lower(WriteBarrierPost writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = g1PostWriteBarrier;
-            Key key = new Key(method);
-            key.add("usePrecise", writeBarrierPost.usePrecise());
-            Arguments arguments = new Arguments();
-            arguments.add("object", writeBarrierPost.getObject());
-            arguments.add("location", writeBarrierPost.getLocation());
-            arguments.add("value", writeBarrierPost.getValue());
-            SnippetTemplate template = cache.get(key, assumptions);
-            template.instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, arguments);
-        }
-
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,13 +27,15 @@
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -44,15 +46,20 @@
  */
 public class NewArrayStub extends Stub {
 
-    public NewArrayStub(final HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) {
-        super(runtime, assumptions, target, NewArrayStubCall.NEW_ARRAY);
+    public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
+        super(runtime, replacements, target, linkage, "newArray");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.add("length", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub"));
+        return args;
     }
 
     /**
@@ -65,7 +72,7 @@
      * @param log specifies if logging is enabled
      */
     @Snippet
-    private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,18 +23,21 @@
 package com.oracle.graal.hotspot.stubs;
 
 import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*;
-import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -45,15 +48,19 @@
  */
 public class NewInstanceStub extends Stub {
 
-    public NewInstanceStub(final HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) {
-        super(runtime, assumptions, target, NEW_INSTANCE);
+    public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
+        super(runtime, replacements, target, linkage, "newInstance");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+        return args;
     }
 
     /**
@@ -64,7 +71,7 @@
      * @param intArrayHub the hub for {@code int[].class}
      */
     @Snippet
-    private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
@@ -92,9 +99,6 @@
      *         operation was unsuccessful
      */
     static Word refillAllocate(Word intArrayHub, int sizeInBytes, boolean log) {
-        if (useG1GC()) {
-            return Word.zero();
-        }
         if (!useTLAB()) {
             return edenAllocate(Word.unsigned(sizeInBytes), log);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,13 +22,9 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
-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.*;
@@ -37,26 +33,28 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 
 /**
  * Base class for implementing some low level code providing the out-of-line slow path for a
  * snippet. A concrete stub is defined a subclass of this class.
  * <p>
  * Implementation detail: The stub classes re-use some of the functionality for {@link Snippet}s
- * purely for convenience (e.g., can re-use the {@link ReplacementsInstaller}).
+ * purely for convenience (e.g., can re-use the {@link ReplacementsImpl}).
  */
 public abstract class Stub extends AbstractTemplates implements Snippets {
 
     /**
      * The method implementing the stub.
      */
-    protected final HotSpotResolvedJavaMethod stubMethod;
+    protected final SnippetInfo stubInfo;
 
     /**
      * The linkage information for the stub.
@@ -69,23 +67,22 @@
     protected InstalledCode stubCode;
 
     /**
-     * Creates a new stub container. The new stub still needs to be {@linkplain #install(Backend)
-     * installed}.
+     * Creates a new stub container. The new stub still needs to be
+     * {@linkplain #getAddress(Backend) installed}.
      * 
-     * @param descriptor linkage details for a call to the stub
+     * @param linkage linkage details for a call to the stub
      */
-    @SuppressWarnings("unchecked")
-    public Stub(HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target, Descriptor descriptor) {
-        super(runtime, assumptions, target, null);
-        stubMethod = findStubMethod(runtime, getClass());
-        linkage = runtime.registerStub(descriptor, this);
-        assert linkage != null;
+    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) {
+        super(runtime, replacements, target);
+        this.stubInfo = snippet(getClass(), methodName);
+        this.linkage = linkage;
+
     }
 
     /**
      * Adds the {@linkplain ConstantParameter constant} arguments of this stub.
      */
-    protected abstract void populateKey(Key key);
+    protected abstract Arguments makeArguments(SnippetInfo stub);
 
     protected HotSpotRuntime runtime() {
         return (HotSpotRuntime) runtime;
@@ -95,7 +92,7 @@
      * Gets the method implementing this stub.
      */
     public ResolvedJavaMethod getMethod() {
-        return stubMethod;
+        return stubInfo.getMethod();
     }
 
     public HotSpotRuntimeCallTarget getLinkage() {
@@ -103,53 +100,37 @@
     }
 
     /**
-     * Compiles the code for this stub, installs it and initializes the address used for calls to
-     * it.
+     * Ensures the code for this stub is installed.
+     * 
+     * @return the entry point address for calls to this stub
      */
-    public void install(Backend backend) {
-        StructuredGraph graph = (StructuredGraph) stubMethod.getCompilerStorage().get(Snippet.class);
+    public synchronized long getAddress(Backend backend) {
+        if (stubCode == null) {
+            Arguments args = makeArguments(stubInfo);
+            SnippetTemplate template = template(args);
+            StructuredGraph graph = template.copySpecializedGraph();
 
-        Key key = new Key(stubMethod);
-        populateKey(key);
-        SnippetTemplate template = cache.get(key, assumptions);
-        graph = template.copySpecializedGraph();
-
-        PhasePlan phasePlan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
-        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL,
-                        new SpeculationLog());
-
-        stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() {
+            PhasePlan phasePlan = new PhasePlan();
+            GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+            phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+            final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL,
+                            new SpeculationLog());
 
-            @Override
-            public InstalledCode call() {
-                InstalledCode installedCode = runtime().addMethod(stubMethod, compResult);
-                assert installedCode != null : "error installing stub " + stubMethod;
-                if (Debug.isDumpEnabled()) {
-                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
-                }
-                return installedCode;
-            }
-        });
-
-        assert stubCode != null : "error installing stub " + stubMethod;
-        linkage.setAddress(stubCode.getStart());
-    }
+            stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable<InstalledCode>() {
 
-    /**
-     * Finds the static method annotated with {@link Snippet} in a given class of which there must
-     * be exactly one.
-     */
-    private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class<?> stubClass) {
-        HotSpotResolvedJavaMethod m = null;
-        for (Method candidate : stubClass.getDeclaredMethods()) {
-            if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) {
-                assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-                m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate);
-            }
+                @Override
+                public InstalledCode call() {
+                    InstalledCode installedCode = runtime().addMethod(getMethod(), compResult);
+                    assert installedCode != null : "error installing stub " + getMethod();
+                    if (Debug.isDumpEnabled()) {
+                        Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
+                    }
+                    return installedCode;
+                }
+            });
+
+            assert stubCode != null : "error installing stub " + getMethod();
         }
-        assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-        return m;
+        return stubCode.getStart();
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Mon Apr 15 08:51:19 2013 +0200
@@ -102,6 +102,13 @@
                         buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc));
                         break;
                     }
+                    case INVOKEDYNAMIC: {
+                        int cpi = stream.readCPI4();
+                        JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        buf.append(String.format("#%-10d // %s", cpi, calleeDesc));
+                        break;
+                    }
                     case LDC            :
                     case LDC_W          :
                     case LDC2_W         : {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
 
 public class GraphBuilderConfiguration {
 
@@ -30,6 +31,13 @@
     private final boolean omitAllExceptionEdges;
     private ResolvedJavaType[] skippedExceptionTypes;
 
+    /**
+     * When the graph builder is in eager infopoint mode, it inserts {@link InfopointNode}s in
+     * places where no safepoints would be inserted: inlining boundaries, and line number switches.
+     * This is relevant when code is to be generated for native, machine-code level debugging.
+     */
+    private boolean eagerInfopointMode;
+
     protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
@@ -39,6 +47,10 @@
         this.skippedExceptionTypes = skippedExceptionTypes;
     }
 
+    public void setEagerInfopointMode(boolean eagerInfopointMode) {
+        this.eagerInfopointMode = eagerInfopointMode;
+    }
+
     public ResolvedJavaType[] getSkippedExceptionTypes() {
         return skippedExceptionTypes;
     }
@@ -51,6 +63,10 @@
         return omitAllExceptionEdges;
     }
 
+    public boolean eagerInfopointMode() {
+        return eagerInfopointMode;
+    }
+
     public static GraphBuilderConfiguration getDefault() {
         return new GraphBuilderConfiguration(false, false);
     }
@@ -64,9 +80,9 @@
     }
 
     /**
-     * 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}.
+     * 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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.code.TypeCheckHints.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static java.lang.reflect.Modifier.*;
@@ -74,6 +75,10 @@
      */
     public static final int TRACELEVEL_STATE = 2;
 
+    private LineNumberTable lnt;
+    private int previousLineNumber;
+    private int currentLineNumber;
+
     protected StructuredGraph currentGraph;
 
     private final MetaAccessProvider runtime;
@@ -140,6 +145,10 @@
     @Override
     protected void run(StructuredGraph graph) {
         method = graph.method();
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            lnt = method.getLineNumberTable();
+            previousLineNumber = -1;
+        }
         entryBCI = graph.getEntryBCI();
         profilingInfo = method.getProfilingInfo();
         assert method.getCode() != null : "method must contain bytecodes: " + method;
@@ -192,6 +201,13 @@
         }
         frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn);
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START));
+            lastInstr.setNext(ipn);
+            lastInstr = ipn;
+        }
+
         // finish the start block
         ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
 
@@ -771,12 +787,12 @@
     }
 
     private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) {
-        if (!optimisticOpts.useTypeCheckHints() || TypeCheckHints.canHaveSubtype(type)) {
+        if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) {
             return null;
         } else {
             ResolvedJavaType uniqueSubtype = type.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                return new JavaTypeProfile(0.0D, new ProfiledType(uniqueSubtype, 1.0D));
+                return new JavaTypeProfile(profilingInfo.getNullSeen(bci()), 0.0D, new ProfiledType(uniqueSubtype, 1.0D));
             } else {
                 return profilingInfo.getTypeProfile(bci());
             }
@@ -960,7 +976,7 @@
 
     protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) {
         assert receiver != null;
-        if (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE) {
+        if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) {
             return;
         }
 
@@ -1053,10 +1069,35 @@
         }
     }
 
+    private void genInvokeDynamic(JavaMethod target) {
+        if (target instanceof ResolvedJavaMethod) {
+            Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
+            if (appendix != null) {
+                frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
+            }
+            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false));
+            appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
+        } else {
+            handleUnresolvedInvoke(target, InvokeKind.Static);
+        }
+    }
+
     private void genInvokeVirtual(JavaMethod target) {
         if (target instanceof ResolvedJavaMethod) {
-            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
-            genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...)
+            // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
+            // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic
+            boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers());
+            Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
+            if (appendix != null) {
+                frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
+            }
+            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver));
+            if (hasReceiver) {
+                genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            } else {
+                appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
+            }
         } else {
             handleUnresolvedInvoke(target, InvokeKind.Virtual);
         }
@@ -1492,7 +1533,7 @@
     }
 
     private void processBlock(Block block) {
-        // Ignore blocks that have no predecessors by the time it their bytecodes are parsed
+        // Ignore blocks that have no predecessors by the time their bytecodes are parsed
         if (block == null || block.firstInstruction == null) {
             Debug.log("Ignoring block %s", block);
             return;
@@ -1573,6 +1614,12 @@
         }
         ReturnNode returnNode = currentGraph.add(new ReturnNode(x));
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_END));
+            ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI));
+            append(ipn);
+        }
+
         append(returnNode);
     }
 
@@ -1683,6 +1730,16 @@
         BytecodesParsed.add(block.endBci - bci);
 
         while (bci < endBCI) {
+            if (graphBuilderConfig.eagerInfopointMode() && lnt != null) {
+                currentLineNumber = lnt.getLineNumber(bci);
+                if (currentLineNumber != previousLineNumber) {
+                    InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.LINE_NUMBER));
+                    ipn.setStateAfter(frameState.create(bci));
+                    append(ipn);
+                    previousLineNumber = currentLineNumber;
+                }
+            }
+
             // read the opcode
             int opcode = stream.currentBC();
             traceState();
@@ -1936,6 +1993,7 @@
             case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
             case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
             case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
+            case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
             case NEW            : genNewInstance(stream.readCPI()); break;
             case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
             case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Mon Apr 15 08:51:19 2013 +0200
@@ -46,6 +46,7 @@
         return sum;
     }
 
+    // CheckStyle: stop system..print check
     private static void doPrint(int n) {
         for (int i = 0; i < n; i++) {
             System.out.print('x');
@@ -56,6 +57,8 @@
         System.out.println(test(10000));
     }
 
+    // CheckStyle: resume system..print check
+
     @LongTest
     public void run0() throws Throwable {
         runTest("test", 10000);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,43 +35,14 @@
 
 public class AMD64Call {
 
-    @Opcode("CALL_DIRECT")
-    public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public abstract static class CallOp extends AMD64LIRInstruction {
 
         @Def({REG, ILLEGAL}) protected Value result;
         @Use({REG, STACK}) protected Value[] parameters;
         @Temp protected Value[] temps;
         @State protected LIRFrameState state;
 
-        protected final ResolvedJavaMethod callTarget;
-
-        public DirectCallOp(ResolvedJavaMethod 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;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            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;
+        public CallOp(Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
             this.result = result;
             this.parameters = parameters;
             this.state = state;
@@ -80,57 +51,43 @@
         }
 
         @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            directCall(tasm, masm, callTarget, null, false, state);
+        public boolean hasCall() {
+            return true;
         }
     }
 
-    @Opcode("CALL_FAR_RUNTIME")
-    public static class DirectFarRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public abstract static class MethodCallOp extends 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 ResolvedJavaMethod callTarget;
 
-        protected final RuntimeCallTarget callTarget;
-
-        public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+        public MethodCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(result, parameters, temps, state);
             this.callTarget = callTarget;
-            this.result = result;
-            this.parameters = parameters;
-            this.state = state;
-            this.temps = temps;
-            assert temps != null;
-            callTemp = gen.newVariable(Kind.Long);
+        }
+
+    }
+
+    @Opcode("CALL_DIRECT")
+    public static class DirectCallOp extends MethodCallOp {
+
+        public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state);
+            directCall(tasm, masm, callTarget, null, true, state);
         }
     }
 
     @Opcode("CALL_INDIRECT")
-    public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public static class IndirectCallOp extends MethodCallOp {
 
-        @Def({REG, ILLEGAL}) protected Value result;
-        @Use({REG, STACK}) protected Value[] parameters;
         @Use({REG}) protected Value targetAddress;
-        @Temp protected Value[] temps;
-        @State protected LIRFrameState state;
 
-        protected final InvokeTarget callTarget;
-
-        public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
-            this.callTarget = callTarget;
-            this.result = result;
-            this.parameters = parameters;
+        public IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
             this.targetAddress = targetAddress;
-            this.state = state;
-            this.temps = temps;
-            assert temps != null;
         }
 
         @Override
@@ -145,6 +102,50 @@
         }
     }
 
+    public abstract static class RuntimeCallOp extends CallOp {
+
+        protected final RuntimeCallTarget callTarget;
+
+        public RuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(result, parameters, temps, state);
+            this.callTarget = callTarget;
+        }
+
+        @Override
+        public boolean hasCall() {
+            return !callTarget.preservesRegisters();
+        }
+    }
+
+    @Opcode("CALL_NEAR_RUNTIME")
+    public static class DirectNearRuntimeCallOp extends RuntimeCallOp {
+
+        public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, null, false, state);
+        }
+    }
+
+    @Opcode("CALL_FAR_RUNTIME")
+    public static class DirectFarRuntimeCallOp extends RuntimeCallOp {
+
+        @Temp({REG}) protected AllocatableValue callTemp;
+
+        public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
+            callTemp = gen.newVariable(Kind.Long);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state);
+        }
+    }
+
     public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) {
         if (align) {
             emitAlignmentForDirectCall(tasm, masm);
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,9 +36,9 @@
 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,
+    FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
+    DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
+    INEG, LNEG, FNEG, DNEG,
     I2L, L2I, I2B, I2C, I2S,
     F2D, D2F,
     I2F, I2D, F2I, D2I,
@@ -46,6 +46,47 @@
     MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
 
 
+    /**
+     * Unary operation with separate source and destination operand. 
+     */
+    public static class Unary2Op extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+
+        public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXMove.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    /**
+     * Unary operation with single operand for source and destination. 
+     */
+    public static class Unary1Op extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+
+        public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result);
+        }
+    }
+
     public static class Op1Reg extends PTXLIRInstruction {
         @Opcode private final PTXArithmetic opcode;
         @Def({REG, HINT}) protected Value result;
@@ -213,23 +254,70 @@
         }
     }
 
-
-    @SuppressWarnings("unused")
-    protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) {
+    protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm,
+                               PTXAssembler masm, PTXArithmetic opcode, Value result) {
         switch (opcode) {
-            default:   throw GraalInternalError.shouldNotReachHere();
+        case L2I:  masm.and_b32(asIntReg(result), asIntReg(result), 0xFFFFFFFF); break;
+        case I2C:  masm.and_b16(asIntReg(result), asIntReg(result), (short) 0xFFFF); break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
         }
     }
 
     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;
+                case INEG:
+                    masm.neg_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2L:
+                    masm.cvt_s64_s32(asLongReg(dst), asIntReg(src));
+                    break;
+                case I2C:
+                    masm.cvt_b16_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2B:
+                    masm.cvt_s8_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2F:
+                    masm.cvt_f32_s32(asFloatReg(dst), asIntReg(src));
+                    break;
+                case I2D:
+                    masm.cvt_f64_s32(asDoubleReg(dst), asIntReg(src));
+                    break;
+                case FNEG:
+                    masm.neg_f32(asFloatReg(dst), asFloatReg(src));
+                    break;
+                case DNEG:
+                    masm.neg_f64(asDoubleReg(dst), asDoubleReg(src));
+                    break;
+                case F2I:
+                    masm.cvt_s32_f32(asIntReg(dst), asFloatReg(src));
+                    break;
+                case F2L:
+                    masm.cvt_s64_f32(asLongReg(dst), asFloatReg(src));
+                    break;
+                case F2D:
+                    masm.cvt_f64_f32(asDoubleReg(dst), asFloatReg(src));
+                    break;
+                case D2I:
+                    masm.cvt_s32_f64(asIntReg(dst), asDoubleReg(src));
+                    break;
+                case D2L:
+                    masm.cvt_s64_f64(asLongReg(dst), asDoubleReg(src));
+                    break;
+                case D2F:
+                    masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src));
+                    break;
+                case LSHL:
+                    masm.shl_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
+                    break;
+                case LSHR:
+                    masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
+                    break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         } else if (isConstant(src)) {
             switch (opcode) {
@@ -252,33 +340,74 @@
     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();
+            case ISUB:  masm.sub_s32(asIntReg(dst),    tasm.asIntConst(src1),    asIntReg(src2));         break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src2),           tasm.asIntConst(src1));  break;
+            case IDIV:  masm.div_s32(asIntReg(dst),    tasm.asIntConst(src1),    asIntReg(src2));         break;
+            case FSUB:  masm.sub_f32(asFloatReg(dst),  tasm.asFloatConst(src1),  asFloatReg(src2));       break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  tasm.asFloatConst(src1),  asFloatReg(src2));       break;
+            case DSUB:  masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2));      break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2));      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();
+            case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
+            case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
+            case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); 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();
+            case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IDIV:  masm.div_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IOR:    masm.or_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IREM:  masm.rem_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case LADD:  masm.add_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSUB:  masm.sub_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LMUL:  masm.mul_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LDIV:  masm.div_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LAND:  masm.and_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LOR:    masm.or_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSHL:  masm.shl_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSHR:  masm.shr_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   asIntReg(src2));    break;
+            case LREM:  masm.rem_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FSUB:  masm.sub_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FREM:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DSUB:  masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DREM:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         }
 
@@ -289,9 +418,11 @@
     }
 
     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)
+        if (((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)) == false) {
+                throw GraalInternalError.shouldNotReachHere("opcode: "  + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind());
+        }
     }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Mon Apr 15 08:51:19 2013 +0200
@@ -65,11 +65,15 @@
 
     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);
+                    emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y));
+                    break;
+                case FCMP:
+                    emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y));
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -101,18 +105,75 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            Register a = asIntReg(x);
-            Register b = asIntReg(y);
             switch (opcode) {
                 case ICMP:
-                    emitCompareRegReg(masm, condition, a, b);
+                    emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y));
+                    break;
+                case LCMP:
+                    emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y));
+                    break;
+                case FCMP:
+                    emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y));
                     break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         }
     }
 
+    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) {
+        switch (condition) {
+        case EQ:
+            masm.setp_eq_f32(a, b);
+            break;
+        case NE:
+            masm.setp_ne_f32(a, b);
+            break;
+        case LT:
+            masm.setp_lt_f32(a, b);
+            break;
+        case LE:
+            masm.setp_le_f32(a, b);
+            break;
+        case GT:
+            masm.setp_gt_f32(a, b);
+            break;
+        case GE:
+            masm.setp_ge_f32(a, b);
+            break;
+        default:
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) {
+        switch (condition) {
+        case EQ:
+            masm.setp_eq_f64(a, b);
+            break;
+        case NE:
+            masm.setp_ne_f64(a, b);
+            break;
+        case LT:
+            masm.setp_lt_f64(a, b);
+            break;
+        case LE:
+            masm.setp_le_f64(a, b);
+            break;
+        case GT:
+            masm.setp_gt_f64(a, b);
+            break;
+        case GE:
+            masm.setp_ge_f64(a, b);
+            break;
+        default:
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) {
         switch (condition) {
             case EQ:
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,14 +22,28 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.api.code.ValueUtil.asIntReg;
+import static com.oracle.graal.api.code.ValueUtil.asLongReg;
+import static com.oracle.graal.api.code.ValueUtil.asObjectReg;
 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.*;
+import com.oracle.graal.api.code.Register;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.asm.Buffer;
+import com.oracle.graal.asm.Label;
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.asm.ptx.AbstractPTXAssembler;
+import com.oracle.graal.asm.ptx.PTXAssembler;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.LabelRef;
+import com.oracle.graal.lir.StandardOp;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.asm.TargetMethodAssembler;
+import com.oracle.graal.nodes.calc.Condition;
 
 public class PTXControlFlow {
 
@@ -64,7 +78,7 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             masm.at();
             Label l = destination.label();
-            l.addPatchAt(tasm.asm.codeBuffer.position());
+            // l.addPatchAt(tasm.asm.codeBuffer.position());
             String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
             masm.bra(target);
         }
@@ -80,4 +94,176 @@
             condition = condition.negate();
         }
     }
+
+    @SuppressWarnings("unused")
+    public static class CondMoveOp extends PTXLIRInstruction {
+        @Def({REG, HINT}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Use({REG, STACK, CONST}) protected Value falseValue;
+        private final Condition condition;
+
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.result = result;
+            this.condition = condition;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
+            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
+            throw new InternalError("NYI");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class FloatCondMoveOp extends PTXLIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Alive({REG}) protected Value falseValue;
+        private final Condition condition;
+        private final boolean unorderedIsTrue;
+
+        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            this.result = result;
+            this.condition = condition;
+            this.unorderedIsTrue = unorderedIsTrue;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
+            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
+            throw new InternalError("NYI");
+        }
+    }
+
+    public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
+        @Use({CONST}) protected Constant[] keyConstants;
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        @Alive({REG}) protected Value key;
+        @Temp({REG, ILLEGAL}) protected Value scratch;
+
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget,
+                                  Value key, Value scratch) {
+            assert keyConstants.length == keyTargets.length;
+            this.keyConstants = keyConstants;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            if (key.getKind() == Kind.Int) {
+                Register intKey = asIntReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    if (tasm.runtime.needsDataPatch(keyConstants[i])) {
+                        tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
+                    }
+                    long lc = keyConstants[i].asLong();
+                    assert NumUtil.isInt(lc);
+                    masm.setp_eq_s32((int) lc, intKey);
+                    masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
+                    masm.bra(target);
+                }
+            } else if (key.getKind() == Kind.Long) {
+                Register longKey = asLongReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey);
+                    masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
+                    masm.bra(target);
+                }
+            } else if (key.getKind() == Kind.Object) {
+                Register intKey = asObjectReg(key);
+                Register temp = asObjectReg(scratch);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
+                    masm.setp_eq_u32(intKey, temp);
+                    masm.at();
+                    masm.bra(keyTargets[i].label().toString());
+                }
+            } else {
+                throw new GraalInternalError("sequential switch only supported for int, long and object");
+            }
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                // masm.hlt();
+            }
+        }
+
+        @Override
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
+        }
+    }
+
+    public static class TableSwitchOp extends PTXLIRInstruction {
+        private final int lowKey;
+        private final LabelRef defaultTarget;
+        private final LabelRef[] targets;
+        @Alive protected Value index;
+        @Temp protected Value scratch;
+
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets,
+                             Variable index, Variable scratch) {
+            this.lowKey = lowKey;
+            this.defaultTarget = defaultTarget;
+            this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey,
+                                    LabelRef defaultTarget, LabelRef[] targets,
+                                    Register value, Register scratch) {
+        Buffer buf = masm.codeBuffer;
+        // Compare index against jump table bounds
+        int highKey = lowKey + targets.length - 1;
+        if (lowKey != 0) {
+            // subtract the low value from the switch value
+            masm.sub_s32(value, value, lowKey);
+            masm.setp_gt_s32(value, highKey - lowKey);
+        } else {
+            masm.setp_gt_s32(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        if (defaultTarget != null) {
+            masm.at();
+            masm.bra(defaultTarget.label().toString());
+        }
+
+        // address of jump table
+        int tablePos = buf.position();
+
+        JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
+        tasm.compilationResult.addAnnotation(jt);
+
+        // PTX: unimp: tableswitch extract
+    }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Apr 15 08:51:19 2013 +0200
@@ -133,9 +133,27 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Int:
                     masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
+                case Long:
+                    masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Object:
                     masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
@@ -162,11 +180,29 @@
             assert isRegister(input);
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Short:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
                 case Int:
                     masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
                     break;
+                case Long:
+                    masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Object:
+                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
             }
         }
     }
@@ -250,11 +286,20 @@
             case Int:
                 masm.mov_s32(asRegister(result), asRegister(input));
                 break;
+            case Long:
+                masm.mov_s64(asRegister(result), asRegister(input));
+                break;
+            case Float:
+                masm.mov_f32(asRegister(result), asRegister(input));
+                break;
+            case Double:
+                masm.mov_f64(asRegister(result), asRegister(input));
+                break;
             case Object:
                 masm.mov_u64(asRegister(result), asRegister(input));
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
     }
 
@@ -266,8 +311,24 @@
                 }
                 masm.mov_s32(asRegister(result), input.asInt());
                 break;
+            case Long:
+                if (tasm.runtime.needsDataPatch(input)) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                }
+                masm.mov_s64(asRegister(result), input.asLong());
+                break;
+            case Object:
+                if (input.isNull()) {
+                    masm.mov_u64(asRegister(result), 0x0L);
+                } else if (tasm.target.inlineObjects) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                    masm.mov_u64(asRegister(result), 0xDEADDEADDEADDEADL);
+                } else {
+                    masm.mov_u64(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false));
+                }
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.lir;
+
+import static com.oracle.graal.lir.LIRInstruction.Opcode;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits an infopoint (only mark the position).
+ */
+@Opcode("INFOPOINT")
+public class InfopointOp extends LIRInstruction {
+
+    @State protected LIRFrameState state;
+
+    private final InfopointReason reason;
+
+    public InfopointOp(LIRFrameState state, InfopointReason reason) {
+        this.state = state;
+        this.reason = reason;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm) {
+        tasm.recordInfopoint(tasm.asm.codeBuffer.position(), state, reason);
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Apr 15 08:51:19 2013 +0200
@@ -260,8 +260,8 @@
      * Returns true when this instruction is a call instruction that destroys all caller-saved
      * registers.
      */
-    public final boolean hasCall() {
-        return this instanceof StandardOp.CallOp;
+    public boolean hasCall() {
+        return false;
     }
 
     public final void forEachInput(ValueProcedure proc) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 15 08:51:19 2013 +0200
@@ -118,13 +118,6 @@
     }
 
     /**
-     * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved
-     * registers.
-     */
-    public interface CallOp {
-    }
-
-    /**
      * Meta-operation that defines the incoming method parameters. In the LIR, every register and
      * variable must be defined before it is used. This operation is the definition point of method
      * parameters, but is otherwise a no-op. In particular, it is not the actual method prologue.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -101,7 +101,7 @@
 
         Debug.metric("TargetMethods").increment();
         Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize());
-        Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size());
+        Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().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);
@@ -122,7 +122,7 @@
     public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
-            compilationResult.recordSafepoint(pcOffset, info.debugInfo());
+            compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION);
             assert info.exceptionEdge == null;
         }
     }
@@ -137,10 +137,10 @@
         compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
     }
 
-    public void recordSafepoint(int pos, LIRFrameState info) {
-        // safepoints always need debug info
+    public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) {
+        // infopoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
-        compilationResult.recordSafepoint(pos, debugInfo);
+        compilationResult.recordInfopoint(pos, debugInfo, reason);
     }
 
     public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) {
@@ -167,6 +167,36 @@
     }
 
     /**
+     * Returns the float value of any constant that can be represented by a 32-bit float value.
+     */
+    public float asFloatConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Float && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asFloat();
+    }
+
+    /**
+     * Returns the long value of any constant that can be represented by a 64-bit long value.
+     */
+    public long asLongConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Long && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asLong();
+    }
+
+    /**
+     * Returns the double value of any constant that can be represented by a 64-bit float value.
+     */
+    public double asDoubleConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Double && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asDouble();
+    }
+
+    /**
      * Returns the address of a float constant that is embedded as a data references into the code.
      */
     public AbstractAddress asFloatConstRef(Value value) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Apr 15 08:51:19 2013 +0200
@@ -60,7 +60,7 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(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.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,31 +22,21 @@
  */
 package com.oracle.graal.loop.phases;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class LoopFullUnrollPhase extends Phase {
+public class LoopFullUnrollPhase extends BasePhase<HighTierContext> {
 
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
-    private final GraalCodeCacheProvider runtime;
-    private final Assumptions assumptions;
-    private int unrollCount;
 
-    public LoopFullUnrollPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
-    }
-
-    public int getUnrollCount() {
-        return unrollCount;
+    public LoopFullUnrollPhase() {
     }
 
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, HighTierContext context) {
         if (graph.hasLoops()) {
             boolean peeled;
             do {
@@ -56,11 +46,10 @@
                 for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
-                        LoopTransformations.fullUnroll(loop, runtime, assumptions);
+                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions());
                         FULLY_UNROLLED_LOOPS.increment();
                         Debug.dump(graph, "After fullUnroll %s", loop);
                         peeled = true;
-                        unrollCount++;
                         break;
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -186,5 +186,5 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T anchor(@ConstantNodeParameter Stamp stamp);
+    public static native BeginNode anchor(@ConstantNodeParameter Stamp stamp);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -29,7 +29,9 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable {
+public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode {
+
+    @Input private FrameState deoptState;
 
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
@@ -49,10 +51,41 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(action, reason);
+        gen.emitDeoptimize(action, this);
     }
 
     @NodeIntrinsic
     public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason);
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return reason;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.type.*;
+
+public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode {
+
+    @Input private FrameState deoptState;
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp, ValueNode... dependencies) {
+        super(stamp, dependencies);
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.nodes;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Interface that needs to be implemented by nodes which need deoptimization information.
+ * 
+ */
+public interface DeoptimizingNode {
+
+    /**
+     * Returns true if this particular instance needs deoptimization information.
+     * 
+     * @return true if this particular instance needs deoptimization information
+     */
+    boolean canDeoptimize();
+
+    /**
+     * Returns the deoptimization information associated with this node if any.
+     * 
+     * @return the deoptimization information associated with this node if any.
+     */
+    FrameState getDeoptimizationState();
+
+    /**
+     * Set the deoptimization information associated with this node.
+     * 
+     * @param state the FrameState which represents the deoptimization information.
+     */
+    void setDeoptimizationState(FrameState state);
+
+    /**
+     * Returns the reason for deoptimization triggered by this node. If deoptimization at this point
+     * can happen for external reasons (i.e. not explicitely triggered by this node) this method can
+     * return null.
+     * 
+     * @return the reason for deoptimization triggered by this node.
+     */
+    DeoptimizationReason getDeoptimizationReason();
+
+    /**
+     * Returns true if this node needs deoptimization information for stack-walking purposes because
+     * it is a call-site. While most other nodes use deoptimization information representing a state
+     * that happened before them, these nodes use a state that is valid during the call itself.
+     * 
+     * @return true if this node needs deoptimization information for stack-walking purposes.
+     */
+    boolean isCallSiteDeoptimization();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 15 08:51:19 2013 +0200
@@ -239,7 +239,7 @@
                 copy.remove(copy.size() - 1);
             }
             ValueNode lastSlot = copy.get(copy.size() - 1);
-            assert lastSlot.kind().getStackKind() == popKind.getStackKind() || (lastSlot instanceof BoxedVirtualObjectNode && popKind == Kind.Object);
+            assert lastSlot.kind().getStackKind() == popKind.getStackKind();
             copy.remove(copy.size() - 1);
         }
         Collections.addAll(copy, pushedValues);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class GenericArrayRangeWriteBarrier extends FixedWithNextNode implements Node.IterableNodeType {
+
+    @Input private ValueNode dstObject;
+    @Input private ValueNode dstPos;
+    @Input private ValueNode length;
+
+    public ValueNode getDstObject() {
+        return dstObject;
+    }
+
+    public ValueNode getDstPos() {
+        return dstPos;
+    }
+
+    public ValueNode getLength() {
+        return length;
+    }
+
+    public GenericArrayRangeWriteBarrier(ValueNode dstObject, ValueNode dstPos, ValueNode length) {
+        super(StampFactory.forVoid());
+        this.dstObject = dstObject;
+        this.dstPos = dstPos;
+        this.length = length;
+
+    }
+
+    @NodeIntrinsic
+    public static native void insertWriteBarrier(Object dstObject, int dstPos, int length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Nodes of this type are inserted into the graph to denote points of interest to debugging.
+ */
+public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType {
+
+    public final InfopointReason reason;
+
+    public InfopointNode(InfopointReason reason) {
+        super(StampFactory.forVoid());
+        this.reason = reason;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        generator.visitInfopointNode(this);
+    }
+
+    @Override
+    public boolean hasSideEffect() {
+        return false;
+    }
+
+    @Override
+    public void setStateAfter(FrameState state) {
+        // shield this node from frame state removal
+        // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained
+        // FrameState that is correctly dealt with by scheduling and partial escape analysis
+        if (state != null) {
+            super.setStateAfter(state);
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
-public interface Invoke extends StateSplit, Lowerable {
+public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode {
 
     FixedNode next();
 
@@ -41,7 +41,7 @@
 
     int bci();
 
-    FixedNode node();
+    FixedNode asNode();
 
     FrameState stateDuring();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -38,6 +38,7 @@
 public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint {
 
     @Input private final CallTargetNode callTarget;
+    @Input private FrameState deoptState;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
@@ -139,13 +140,16 @@
     }
 
     @Override
-    public FixedNode node() {
+    public FixedNode asNode() {
         return this;
     }
 
     @Override
     public FrameState stateDuring() {
         FrameState stateAfter = stateAfter();
+        if (stateAfter == null) {
+            return null;
+        }
         FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind());
         stateDuring.setDuringCall(true);
         return stateDuring;
@@ -175,4 +179,34 @@
             stateAfter.safeDelete();
         }
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState == null) {
+            FrameState stateDuring = stateDuring();
+            updateUsages(deoptState, stateDuring);
+            deoptState = stateDuring;
+        }
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,6 +37,7 @@
     @Successor private BeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
     @Input private final CallTargetNode callTarget;
+    @Input private FrameState deoptState;
     @Input private FrameState stateAfter;
     private final int bci;
     private boolean polymorphic;
@@ -125,7 +126,7 @@
     }
 
     @Override
-    public FixedNode node() {
+    public FixedNode asNode() {
         return this;
     }
 
@@ -221,4 +222,34 @@
     public double probability(BeginNode successor) {
         return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState == null) {
+            FrameState stateDuring = stateDuring();
+            updateUsages(deoptState, stateDuring);
+            deoptState = stateDuring;
+        }
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -30,23 +31,23 @@
  * A node that changes the type of its input, usually narrowing it. For example, a PI node refines
  * the type of a receiver during type-guarded inlining to be the type tested by the guard.
  */
-public class PiNode extends FloatingNode implements LIRLowerable, Virtualizable {
+public class PiNode extends FloatingNode implements LIRLowerable, Virtualizable, Node.IterableNodeType {
 
     @Input private ValueNode object;
-    @Input(notDataflow = true) private final FixedNode anchor;
 
     public ValueNode object() {
         return object;
     }
 
-    public FixedNode anchor() {
-        return anchor;
+    public PiNode(ValueNode object, Stamp stamp) {
+        super(stamp);
+        this.object = object;
     }
 
-    public PiNode(ValueNode object, FixedNode anchor, Stamp stamp) {
-        super(stamp);
+    public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
+        super(stamp, anchor);
+        assert anchor instanceof FixedNode;
         this.object = object;
-        this.anchor = anchor;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -29,7 +30,7 @@
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
-public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
 
     public SafepointNode() {
         this(StampFactory.forVoid());
@@ -43,4 +44,14 @@
     public void generate(LIRGeneratorTool gen) {
         gen.visitSafepointNode(this);
     }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class SerialArrayRangeWriteBarrier extends FixedWithNextNode implements Lowerable {
+
+    @Input private ValueNode object;
+    @Input private ValueNode startIndex;
+    @Input private ValueNode length;
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public ValueNode getStartIndex() {
+        return startIndex;
+    }
+
+    public ValueNode getLength() {
+        return length;
+    }
+
+    public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.startIndex = startIndex;
+        this.length = length;
+
+    }
+
+    public void lower(LoweringTool generator) {
+        generator.getRuntime().lower(this, generator);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable {
+
+    @Input private ValueNode object;
+    @Input private LocationNode location;
+    private final boolean precise;
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public LocationNode getLocation() {
+        return location;
+    }
+
+    public boolean usePrecise() {
+        return precise;
+    }
+
+    public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.location = location;
+        this.precise = precise;
+    }
+
+    @Override
+    public void lower(LoweringTool generator) {
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -172,5 +172,15 @@
     }
 
     @NodeIntrinsic
-    public static native <S, T> S convert(@ConstantNodeParameter Op op, T value);
+    public static native float convert(@ConstantNodeParameter Op op, int value);
+
+    @NodeIntrinsic
+    public static native int convert(@ConstantNodeParameter Op op, float value);
+
+    @NodeIntrinsic
+    public static native double convert(@ConstantNodeParameter Op op, long value);
+
+    @NodeIntrinsic
+    public static native long convert(@ConstantNodeParameter Op op, double value);
+
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,12 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(shortName = "/")
-public class FixedBinaryNode extends FixedWithNextNode {
+public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -46,4 +44,9 @@
         this.x = x;
         this.y = y;
     }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.ArithmeticException;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -53,6 +53,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -49,6 +49,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -109,6 +109,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -66,6 +66,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -29,7 +29,7 @@
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable {
+public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
 
     @Input private ValueNode object;
 
@@ -78,4 +78,10 @@
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         }
     }
+
+    @Override
+    public boolean push(PiNode parent) {
+        replaceFirstInput(parent, parent.object());
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -81,8 +81,35 @@
             // one of them is virtual: they can never be the same objects
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         } else if (xVirtual && yVirtual) {
-            // both are virtual: check if they refer to the same object
-            tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph()));
+            boolean xIdentity = stateX.getVirtualObject().hasIdentity();
+            boolean yIdentity = stateY.getVirtualObject().hasIdentity();
+            if (xIdentity ^ yIdentity) {
+                /*
+                 * One of the two objects has identity, the other doesn't. In code, this looks like
+                 * "Integer.valueOf(a) == new Integer(b)", which is always false.
+                 * 
+                 * In other words: an object created via valueOf can never be equal to one created
+                 * by new in the same compilation unit.
+                 */
+                tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
+            } else if (!xIdentity && !yIdentity) {
+                // both are virtual without identity: check contents
+                assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1;
+                assert stateX.getVirtualObject().type() == stateY.getVirtualObject().type();
+                assert stateX.getVirtualObject().entryKind(0) == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long;
+                final IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0));
+                tool.customAction(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        graph().add(equals);
+                    }
+                });
+                tool.replaceWithValue(equals);
+            } else {
+                // both are virtual with identity: check if they refer to the same object
+                tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph()));
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -67,6 +67,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -66,6 +66,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -121,6 +121,9 @@
 
     @Override
     public void lower(LoweringTool tool) {
+        if (!enabled) {
+            throw new GraalInternalError("counter nodes shouldn't exist when not enabled");
+        }
         StructuredGraph graph = (StructuredGraph) graph();
         if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) {
             int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
-public interface Access {
+public interface Access extends DeoptimizingNode {
 
     ValueNode object();
 
@@ -33,5 +33,5 @@
 
     void setNullCheck(boolean check);
 
-    Node node();
+    Node asNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,7 @@
  * {@linkplain #nullCheckLocation() location}. The access does not include a null check on the
  * object.
  */
-public abstract class AccessNode extends FixedWithNextNode implements Access {
+public abstract class AccessNode extends DeoptimizingFixedWithNextNode implements Access {
 
     @Input private ValueNode object;
     @Input private ValueNode location;
@@ -78,7 +79,17 @@
     }
 
     @Override
-    public Node node() {
+    public Node asNode() {
         return this;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return nullCheck;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,80 +23,84 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-
-public final class BoxNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Canonicalizable {
+import com.oracle.graal.nodes.virtual.*;
 
-    @Input private ValueNode source;
-    private final int bci;
-    private final Kind sourceKind;
+/**
+ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf
+ * methods in Integer, Long, etc.
+ */
+public class BoxNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Canonicalizable {
 
-    public BoxNode(ValueNode value, ResolvedJavaType type, Kind sourceKind, int bci) {
-        super(StampFactory.exactNonNull(type));
-        this.source = value;
-        this.bci = bci;
-        this.sourceKind = sourceKind;
-        assert value.kind() != Kind.Object : "can only box from primitive type";
+    @Input private ValueNode value;
+    private final Kind boxingKind;
+
+    public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) {
+        super(StampFactory.exactNonNull(resultType));
+        this.value = value;
+        this.boxingKind = boxingKind;
     }
 
-    public ValueNode source() {
-        return source;
-    }
-
-    public Kind getSourceKind() {
-        return sourceKind;
+    public Kind getBoxingKind() {
+        return boxingKind;
     }
 
-    public void expand(BoxingMethodPool pool) {
-        ResolvedJavaMethod boxingMethod = pool.getBoxingMethod(sourceKind);
-        MethodCallTargetNode callTarget = graph().add(
-                        new MethodCallTargetNode(InvokeKind.Static, boxingMethod, new ValueNode[]{source}, boxingMethod.getSignature().getReturnType(boxingMethod.getDeclaringClass())));
-        InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci));
-        invokeNode.setProbability(this.probability());
-        invokeNode.setStateAfter(stateAfter());
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, invokeNode);
+    public ValueNode getValue() {
+        return value;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
+        /*
+         * Constant values are not canonicalized into their constant boxing objects because this
+         * would mean that the information that they came from a valueOf is lost.
+         */
+        if (usages().isEmpty()) {
+            return null;
+        }
+        return this;
+    }
 
-        if (source.isConstant()) {
-            Constant sourceConstant = source.asConstant();
-            switch (sourceKind) {
-                case Boolean:
-                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph());
-                case Byte:
-                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph());
-                case Char:
-                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph());
-                case Short:
-                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph());
-                case Int:
-                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph());
-                case Long:
-                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph());
-                case Float:
-                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph());
-                case Double:
-                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph());
-                default:
-                    assert false : "Unexpected source kind for boxing";
-                    break;
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        ValueNode v = tool.getReplacedValue(getValue());
+        ResolvedJavaType type = objectStamp().type();
+
+        VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
+        assert newVirtual.getFields().length == 1;
+
+        tool.createVirtualObject(newVirtual, new ValueNode[]{v}, 0);
+        tool.replaceWithVirtual(newVirtual);
+    }
+
+    @NodeIntrinsic
+    public static native Boolean box(boolean value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Byte box(byte value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 
-            }
-        }
+    @NodeIntrinsic
+    public static native Character box(char value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Double box(double value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Float box(float value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 
-        for (Node usage : usages()) {
-            if (usage != stateAfter()) {
-                return this;
-            }
-        }
-        replaceAtUsages(null);
-        return null;
-    }
+    @NodeIntrinsic
+    public static native Integer box(int value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Long box(long value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Short box(short value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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.nodes.extended;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-
-public class BoxingMethodPool {
-
-    private final Set<JavaMethod> specialMethods = new HashSet<>();
-    private final MetaAccessProvider runtime;
-    private final ResolvedJavaMethod[] boxingMethods = new ResolvedJavaMethod[Kind.values().length];
-    private final ResolvedJavaMethod[] unboxingMethods = new ResolvedJavaMethod[Kind.values().length];
-    private final ResolvedJavaField[] boxFields = new ResolvedJavaField[Kind.values().length];
-
-    public BoxingMethodPool(MetaAccessProvider runtime) {
-        this.runtime = runtime;
-
-        try {
-            initialize(Kind.Boolean, Boolean.class, "booleanValue");
-            initialize(Kind.Byte, Byte.class, "byteValue");
-            initialize(Kind.Char, Character.class, "charValue");
-            initialize(Kind.Short, Short.class, "shortValue");
-            initialize(Kind.Int, Integer.class, "intValue");
-            initialize(Kind.Long, Long.class, "longValue");
-            initialize(Kind.Float, Float.class, "floatValue");
-            initialize(Kind.Double, Double.class, "doubleValue");
-        } catch (SecurityException | NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private void initialize(Kind kind, Class<?> type, String unboxMethod) throws SecurityException, NoSuchMethodException {
-        // Get boxing method from runtime.
-        ResolvedJavaMethod boxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod("valueOf", kind.toJavaClass()));
-        specialMethods.add(boxingMethod);
-        boxingMethods[kind.ordinal()] = boxingMethod;
-
-        // Get unboxing method from runtime.
-        ResolvedJavaMethod unboxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod(unboxMethod));
-        unboxingMethods[kind.ordinal()] = unboxingMethod;
-        specialMethods.add(unboxingMethod);
-
-        // Get the field that contains the boxed value.
-        ResolvedJavaField[] fields = runtime.lookupJavaType(type).getInstanceFields(false);
-        ResolvedJavaField boxField = fields[0];
-        assert fields.length == 1 && boxField.getKind() == kind;
-        boxFields[kind.ordinal()] = boxField;
-    }
-
-    public boolean isSpecialMethod(ResolvedJavaMethod method) {
-        return specialMethods.contains(method);
-    }
-
-    public boolean isBoxingMethod(ResolvedJavaMethod method) {
-        return isSpecialMethod(method) && method.getSignature().getReturnKind() == Kind.Object;
-    }
-
-    public boolean isUnboxingMethod(ResolvedJavaMethod method) {
-        return isSpecialMethod(method) && method.getSignature().getReturnKind() != Kind.Object;
-    }
-
-    public ResolvedJavaMethod getBoxingMethod(Kind kind) {
-        return boxingMethods[kind.ordinal()];
-    }
-
-    public ResolvedJavaMethod getUnboxingMethod(Kind kind) {
-        return unboxingMethods[kind.ordinal()];
-    }
-
-    public ResolvedJavaField getBoxField(Kind kind) {
-        return boxFields[kind.ordinal()];
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,7 @@
 
 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.*;
@@ -33,6 +34,7 @@
 
     @Input private ValueNode object;
     @Input private LocationNode location;
+    @Input private FrameState deoptState;
     private boolean nullCheck;
 
     public ValueNode object() {
@@ -74,9 +76,35 @@
     }
 
     @Override
-    public Node node() {
+    public Node asNode() {
         return this;
     }
 
+    @Override
+    public boolean canDeoptimize() {
+        return nullCheck;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+
     public abstract Access asFixedNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -53,7 +53,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -86,12 +86,12 @@
     }
 
     @Override
-    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) {
-        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), canTrap);
+    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), deopting);
     }
 
     @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);
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), deopting);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -60,17 +60,12 @@
 
     /**
      * 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.
+     * analysis of memory accesses in a graph. 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 ANY_LOCATION = createLocation("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 = createLocation("FINAL_LOCATION");
@@ -112,11 +107,11 @@
         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 Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, deopting);
     }
 
-    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);
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), deopting);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public class NullCheckNode extends FixedWithNextNode implements LIRLowerable {
+public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
     @Input public ValueNode object;
 
@@ -41,6 +42,16 @@
 
     @Override
     public void generate(LIRGeneratorTool generator) {
-        generator.emitNullCheck(object);
+        generator.emitNullCheck(object, this);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
 /**
  * Reads an {@linkplain AccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
+public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable {
 
     public ReadNode(ValueNode object, ValueNode location, Stamp stamp) {
         super(object, location, stamp);
@@ -57,7 +57,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), this));
     }
 
     @Override
@@ -98,6 +98,21 @@
         return read;
     }
 
+    @Override
+    public boolean push(PiNode parent) {
+        Object locId = location().locationIdentity();
+        if (locId instanceof ResolvedJavaField) {
+            ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass();
+            ResolvedJavaType beforePiType = parent.object().objectStamp().type();
+
+            if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) {
+                replaceFirstInput(parent, parent.object());
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Reads a value from memory.
      * 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -30,9 +30,10 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "RuntimeCall#{p#descriptor/s}")
-public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable {
+public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable, DeoptimizingNode {
 
     private final Descriptor descriptor;
+    @Input private FrameState deoptState;
 
     public RuntimeCallNode(Descriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments);
@@ -65,4 +66,43 @@
         }
         return super.toString(verbosity);
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState != null) {
+            return deoptState;
+        } else if (stateAfter() != null) {
+            FrameState stateDuring = stateAfter();
+            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
+                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
+            }
+            updateUsages(deoptState, stateDuring);
+            return deoptState = stateDuring;
+        }
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        if (deoptState != null) {
+            throw new IllegalStateException();
+        }
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return stateAfter() != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,47 +23,49 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class UnboxNode extends FixedWithNextNode implements Node.IterableNodeType, Canonicalizable {
+public class UnboxNode extends FixedWithNextNode implements Virtualizable, Lowerable, Canonicalizable {
 
-    @Input private ValueNode source;
-    private Kind destinationKind;
+    @Input private ValueNode value;
+    private final Kind boxingKind;
 
-    public UnboxNode(Kind kind, ValueNode source) {
-        super(StampFactory.forKind(kind));
-        this.source = source;
-        this.destinationKind = kind;
-        assert kind != Kind.Object : "can only unbox to primitive";
-        assert source.kind() == Kind.Object : "can only unbox objects";
+    public UnboxNode(ValueNode value, Kind boxingKind) {
+        super(StampFactory.forKind(boxingKind.getStackKind()));
+        this.value = value;
+        this.boxingKind = boxingKind;
+    }
+
+    public Kind getBoxingKind() {
+        return boxingKind;
     }
 
-    public ValueNode source() {
-        return source;
+    public ValueNode getValue() {
+        return value;
     }
 
-    public Kind destinationKind() {
-        return destinationKind;
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
     }
 
-    public void expand(BoxingMethodPool pool) {
-        ResolvedJavaField field = pool.getBoxField(kind());
-        LoadFieldNode loadField = graph().add(new LoadFieldNode(source, field));
-        loadField.setProbability(probability());
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, loadField);
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(value);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            tool.replaceWithValue(state.getEntry(0));
+        }
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (source.isConstant()) {
-            Constant constant = source.asConstant();
+        if (value.isConstant()) {
+            Constant constant = value.asConstant();
             Object o = constant.asObject();
             if (o != null) {
-                switch (destinationKind) {
+                switch (boxingKind) {
                     case Boolean:
                         return ConstantNode.forBoolean((Boolean) o, graph());
                     case Byte:
@@ -84,7 +86,36 @@
                         ValueNodeUtil.shouldNotReachHere();
                 }
             }
+        } else if (value instanceof BoxNode) {
+            return ((BoxNode) value).getValue();
+        }
+        if (usages().isEmpty()) {
+            return null;
         }
         return this;
     }
+
+    @NodeIntrinsic
+    public static native boolean unbox(Boolean value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native byte unbox(Byte value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native char unbox(Character value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native double unbox(Double value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native float unbox(Float value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native int unbox(Integer value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native long unbox(Long value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native short unbox(Short value, @ConstantNodeParameter Kind kind);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,8 +37,8 @@
         return length;
     }
 
-    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) {
-        super(object, stamp);
+    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) {
+        super(object, stamp, anchor);
         this.length = length;
     }
 
@@ -51,5 +51,5 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp);
+    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,29 +24,20 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
  */
-public class UnsafeCastNode extends FloatingNode implements Canonicalizable, LIRLowerable {
-
-    @Input private ValueNode object;
-
-    public ValueNode object() {
-        return object;
-    }
+public class UnsafeCastNode extends PiNode implements Canonicalizable, LIRLowerable {
 
     public UnsafeCastNode(ValueNode object, Stamp stamp) {
-        super(stamp);
-        this.object = object;
+        super(object, stamp);
     }
 
     public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
-        super(stamp, anchor);
-        this.object = object;
+        super(object, stamp, anchor);
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
@@ -72,13 +63,13 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (kind() != object.kind()) {
+        if (kind() != object().kind()) {
             return this;
         }
 
         if (kind() == Kind.Object) {
             ObjectStamp my = objectStamp();
-            ObjectStamp other = object.objectStamp();
+            ObjectStamp other = object().objectStamp();
 
             if (my.type() == null || other.type() == null) {
                 return this;
@@ -93,21 +84,21 @@
                 return this;
             }
         }
-        return object;
+        return object();
     }
 
     @Override
     public void generate(LIRGeneratorTool generator) {
-        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";
+        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(result, generator.operand(object));
+            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
             // we do not have to
             // introduce a new operand when the kind is the same.
-            generator.setResult(this, generator.operand(object));
+            generator.setResult(this, generator.operand(object()));
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,14 +25,34 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.graph.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
+    private final WriteBarrierType barrierType;
+
+    /*
+     * The types of write barriers attached to stores.
+     */
+    public enum WriteBarrierType {
+        /*
+         * Primitive stores which do not necessitate write barriers.
+         */
+        NONE,
+        /*
+         * Array object stores which necessitate precise write barriers.
+         */
+        PRECISE,
+        /*
+         * Field object stores which necessitate imprecise write barriers.
+         */
+        IMPRECISE
+    }
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -52,18 +72,23 @@
         return value;
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location) {
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType) {
         super(object, location, StampFactory.forVoid());
         this.value = value;
+        this.barrierType = barrierType;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        location().generateStore(gen, object(), value(), getNullCheck());
+        location().generateStore(gen, object(), value(), this);
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Object location);
+    public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers);
 
     @Override
     public Object[] getLocationIdentities() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release.
@@ -72,7 +73,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual) {
+        if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().getClass() == VirtualInstanceNode.class) {
             Debug.log("monitor operation %s on %s\n", this, state);
             int newLockCount = state.getLockCount() + (this instanceof MonitorEnterNode ? 1 : -1);
             state.setLockCount(newLockCount);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -41,7 +41,7 @@
      * @param object the instruction producing the object
      */
     public CheckCastDynamicNode(ValueNode type, ValueNode object) {
-        super(StampFactory.object());
+        super(object.stamp());
         this.type = type;
         this.object = object;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -102,7 +102,9 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
         if (state != null && state.getState() == EscapeState.Virtual) {
-            tool.replaceWithVirtual(state.getVirtualObject());
+            if (type.isAssignableFrom(state.getVirtualObject().type())) {
+                tool.replaceWithVirtual(state.getVirtualObject());
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,8 +25,10 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 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.extended.WriteNode.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -34,13 +36,14 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint {
+public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
     private final int displacement;
+    private WriteBarrierType barrierType;
 
     public ValueNode object() {
         return object;
@@ -62,6 +65,14 @@
         return displacement;
     }
 
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    public void setWriteBarrierType(WriteBarrierType type) {
+        this.barrierType = type;
+    }
+
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
@@ -70,6 +81,7 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
+        this.barrierType = WriteBarrierType.NONE;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -29,16 +29,13 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * The {@code ExceptionObject} instruction represents the incoming exception object to an exception
- * handler.
+ * The entry to an exception handler with the exception coming from a call (as opposed to a local
+ * throw instruction or implicit exception).
  */
-public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, LIRLowerable, MemoryCheckpoint {
+public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint {
 
-    /**
-     * Constructs a new ExceptionObject instruction.
-     */
     public ExceptionObjectNode(MetaAccessProvider runtime) {
-        super(StampFactory.declared(runtime.lookupJavaType(Throwable.class)));
+        super(StampFactory.declaredNonNull(runtime.lookupJavaType(Throwable.class)));
     }
 
     @Override
@@ -47,23 +44,35 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.visitExceptionObject(this);
+    public void simplify(SimplifierTool tool) {
+        //
+    }
+
+    private boolean isLowered() {
+        return (stamp() == StampFactory.forVoid());
     }
 
     @Override
     public void lower(LoweringTool tool) {
-        tool.getRuntime().lower(this, tool);
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        //
+        if (isLowered()) {
+            return;
+        }
+        StructuredGraph graph = (StructuredGraph) graph();
+        LoadExceptionObjectNode loadException = graph.add(new LoadExceptionObjectNode(stamp()));
+        loadException.setStateAfter(stateAfter());
+        replaceAtUsages(loadException);
+        graph.addAfterFixed(this, loadException);
+        tool.setLastFixedNode(loadException);
+        setStateAfter(null);
+        setStamp(StampFactory.forVoid());
     }
 
     @Override
     public boolean verify() {
-        assertTrue(stateAfter() != null, "an exception handler needs a frame state");
+        if (isLowered()) {
+            return true;
+        }
+        assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
         return super.verify();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009, 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.java;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Loads an exception object passed by the runtime from a callee to an exception handler in a
+ * caller. The node is only produced when lowering an {@link ExceptionObjectNode}.
+ */
+public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable {
+
+    public LoadExceptionObjectNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,10 +33,11 @@
  * 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, Virtualizable {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
 
     public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class);
 
+    @Input private FrameState deoptState;
     @Input private ValueNode object;
 
     public ValueNode object() {
@@ -50,7 +52,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(REGISTER_FINALIZER);
-        gen.emitCall(call, call.getCallingConvention(), true, gen.operand(object()));
+        gen.emitCall(call, call.getCallingConvention(), this, gen.operand(object()));
     }
 
     @Override
@@ -63,7 +65,8 @@
         } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) {
             // if either the declared type of receiver or the holder
             // can be assumed to have no finalizers
-            if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) {
+            if (tool.assumptions().useOptimisticAssumptions()) {
+                tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type());
                 needsCheck = false;
             }
         }
@@ -83,6 +86,32 @@
         }
     }
 
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 
 /**
@@ -30,5 +31,17 @@
  */
 public interface GraalCodeCacheProvider extends CodeCacheProvider {
 
+    /**
+     * Adds the given compilation result as an implementation of the given method without making it
+     * the default implementation. The graph might be inlined later on.
+     * 
+     * @param method a method to which the executable code is begin added
+     * @param compResult the compilation result to be added
+     * @param graph the graph that represents the method
+     * @return a reference to the compiled and ready-to-run code or null if the code installation
+     *         failed
+     */
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph);
+
     void lower(Node n, LoweringTool tool);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Mon Apr 15 08:51:19 2013 +0200
@@ -57,9 +57,9 @@
 
     public abstract void emitMove(Value dst, Value src);
 
-    public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap);
+    public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting);
 
-    public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap);
+    public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode deopting);
 
     public abstract Value emitLea(Value base, int displacement, Value index, int scale);
 
@@ -73,13 +73,13 @@
 
     public abstract Value emitMul(Value a, Value b);
 
-    public abstract Value emitDiv(Value a, Value b);
+    public abstract Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitRem(Value a, Value b);
+    public abstract Value emitRem(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitUDiv(Value a, Value b);
+    public abstract Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitURem(Value a, Value b);
+    public abstract Value emitURem(Value a, Value b, DeoptimizingNode deopting);
 
     public abstract Value emitAnd(Value a, Value b);
 
@@ -97,11 +97,11 @@
 
     public abstract void emitMembar(int barriers);
 
-    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason);
+    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting);
 
-    public abstract void emitNullCheck(ValueNode v);
+    public abstract void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
-    public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args);
+    public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args);
 
     public abstract void emitIf(IfNode i);
 
@@ -123,7 +123,6 @@
     public abstract void visitCompareAndSwap(CompareAndSwapNode i);
 
     // These methods define the contract a runtime specific backend must provide.
-    public abstract void visitExceptionObject(ExceptionObjectNode i);
 
     public abstract void visitReturn(ReturnNode i);
 
@@ -138,4 +137,6 @@
      */
     public void beforeRegisterAllocation() {
     }
+
+    public abstract void visitInfopointNode(InfopointNode i);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,6 +34,8 @@
 
     GraalCodeCacheProvider getRuntime();
 
+    Replacements getReplacements();
+
     ValueNode createNullCheckGuard(ValueNode object);
 
     ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.nodes.spi;
+
+import java.lang.annotation.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Denotes a macro substitute method. This replaces a method invocation with an instance of the
+ * specified node class.
+ * 
+ * A macro substitution can be combined with a normal substitution, so that the macro node can be
+ * replaced with the actual substitution code during lowering.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface MacroSubstitution {
+
+    /**
+     * Gets the name of the substituted method.
+     * <p>
+     * If the default value is specified for this element, then the name of the substituted method
+     * is same as the substitute method.
+     */
+    String value() default "";
+
+    /**
+     * Determines if the substituted method is static.
+     */
+    boolean isStatic() default true;
+
+    /**
+     * Gets the {@linkplain MetaUtil#signatureToMethodDescriptor signature} of the substituted
+     * method.
+     * <p>
+     * If the default value is specified for this element, then the signature of the substituted
+     * method is the same as the substitute method.
+     */
+    String signature() default "";
+
+    /**
+     * Determines if the substitution is for a method that may not be part of the runtime. For
+     * example, a method introduced in a later JDK version. Substitutions for such methods are
+     * omitted if the original method cannot be found.
+     */
+    boolean optional() default false;
+
+    /**
+     * The node class with which the method invocation should be replaced. It needs to be a subclass
+     * of {@link FixedWithNextNode}, and it is expected to provide a public constructor that takes
+     * an {@link InvokeNode} as a parameter.
+     */
+    Class<? extends FixedWithNextNode> macro();
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     * 
+     * Not that this is still depending on whether inlining sees the correct call target, so it's
+     * only a hard guarantee for static and special invocations.
+     */
+    boolean forced() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/PiPushable.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.spi;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * This interface marks nodes, which are able to be pushed through a PiNode.
+ */
+public interface PiPushable {
+
+    /**
+     * 
+     * @param parent PiNode
+     * @return true if node was moved
+     */
+    boolean push(PiNode parent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.spi;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Interface for managing replacements.
+ */
+public interface Replacements {
+
+    /**
+     * Gets the snippet graph derived from a given method.
+     * 
+     * @return the snippet graph, if any, that is derived from {@code method}
+     */
+    StructuredGraph getSnippet(ResolvedJavaMethod method);
+
+    /**
+     * Gets the graph that is a substitution for a given method.
+     * 
+     * @return the graph, if any, that is a substitution for {@code method}
+     */
+    StructuredGraph getMethodSubstitution(ResolvedJavaMethod method);
+
+    /**
+     * Gets the node class with which a method invocation should be replaced.
+     * 
+     * @param method target of an invocation
+     * @return the {@linkplain MacroSubstitution#macro() macro node class} associated with
+     *         {@code method} or null if there is no such association
+     */
+    Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method);
+
+    /**
+     * Gets the assumptions with which replacement graphs are preprocessed.
+     */
+    Assumptions getAssumptions();
+
+    /**
+     * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution
+     * macro} substitutions defined by a given class.
+     */
+    void registerSubstitutions(Class<?> substitutions);
+
+    /**
+     * Returns all methods that are currently registered as method/macro substitution or as a
+     * snippet.
+     */
+    Collection<ResolvedJavaMethod> getAllReplacements();
+
+    /**
+     * Determines whether the replacement of this method is flagged as being inlined always.
+     */
+    boolean isForcedSubstitution(ResolvedJavaMethod methodAt);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.spi;
+
+/**
+ * Interface for service providers that register replacements with the compiler.
+ */
+public interface ReplacementsProvider {
+
+    void registerReplacements(Replacements replacements);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,12 +23,15 @@
 package com.oracle.graal.nodes.type;
 
 import com.oracle.graal.api.code.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.GenericStamp.GenericStampType;
 
 public class StampFactory {
 
+    // JaCoCo Exclude
+
     private static final Stamp[] stampCache = new Stamp[Kind.values().length];
     private static final Stamp objectStamp = new ObjectStamp(null, false, false, false);
     private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Apr 15 08:51:19 2013 +0200
@@ -202,7 +202,7 @@
         while (n != null) {
             if (n instanceof MethodCallTargetNode) {
                 elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1));
-                n = ((MethodCallTargetNode) n).invoke().node();
+                n = ((MethodCallTargetNode) n).invoke().asNode();
             }
 
             if (n instanceof StateSplit) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ /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.nodes.virtual;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class BoxedVirtualObjectNode extends VirtualObjectNode implements LIRLowerable, Node.ValueNumberable {
-
-    @Input ValueNode unboxedValue;
-    private final ResolvedJavaType type;
-    private final Kind kind;
-
-    public BoxedVirtualObjectNode(ResolvedJavaType type, Kind kind, ValueNode unboxedValue) {
-        this.type = type;
-        this.kind = kind;
-        this.unboxedValue = unboxedValue;
-    }
-
-    public ValueNode getUnboxedValue() {
-        return unboxedValue;
-    }
-
-    @Override
-    public ResolvedJavaType type() {
-        return type;
-    }
-
-    @Override
-    public int entryCount() {
-        return 1;
-    }
-
-    @Override
-    public String fieldName(int index) {
-        assert index == 0;
-        return "value";
-    }
-
-    @Override
-    public int entryIndexForOffset(long constantOffset) {
-        // (lstadler) unsafe access to a newly created boxing object should only ever touch the
-        // value field
-        return 0;
-    }
-
-    @Override
-    public Kind entryKind(int index) {
-        return kind;
-    }
-
-    @Override
-    public BoxedVirtualObjectNode duplicate() {
-        return new BoxedVirtualObjectNode(type, kind, unboxedValue);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,10 +22,14 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]")
@@ -137,4 +141,19 @@
     public VirtualArrayNode duplicate() {
         return new VirtualArrayNode(componentType, length);
     }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        ResolvedJavaType element = componentType();
+        NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount(), graph), defaultValuesOnly, lockCount > 0));
+        materializeNode.replaceAtUsages(newArray);
+        graph.addBeforeFixed(materializeNode, newArray);
+        if (!defaultValuesOnly) {
+            for (int i = 0; i < entryCount(); i++) {
+                graph.addBeforeFixed(materializeNode, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i))));
+            }
+        }
+        graph.removeFixed(materializeNode);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.virtual;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class VirtualBoxingNode extends VirtualInstanceNode {
+
+    private final Kind boxingKind;
+
+    public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) {
+        super(type);
+        this.boxingKind = boxingKind;
+    }
+
+    @Override
+    public VirtualBoxingNode duplicate() {
+        return new VirtualBoxingNode(type(), boxingKind);
+    }
+
+    @Override
+    public boolean hasIdentity() {
+        return false;
+    }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        assert values.size() == 1;
+        assert lockCount == 0;
+        StructuredGraph graph = (StructuredGraph) graph();
+        BoxNode valueOf = graph.add(new BoxNode(values.get(0), type(), boxingKind));
+        graph.replaceFixedWithFixed(materializeNode, valueOf);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 
 @NodeInfo(nameTemplate = "VirtualInstance {p#type}")
 public class VirtualInstanceNode extends VirtualObjectNode {
@@ -93,4 +97,18 @@
     public VirtualInstanceNode duplicate() {
         return new VirtualInstanceNode(type);
     }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        NewInstanceNode newInstance = graph.add(new NewInstanceNode(type(), defaultValuesOnly, lockCount > 0));
+        materializeNode.replaceAtUsages(newInstance);
+        graph.addBeforeFixed(materializeNode, newInstance);
+        if (!defaultValuesOnly) {
+            for (int i = 0; i < entryCount(); i++) {
+                graph.addBeforeFixed(materializeNode, graph.add(new StoreFieldNode(newInstance, field(i), values.get(i))));
+            }
+        }
+        graph.removeFixed(materializeNode);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -46,13 +48,15 @@
 
     public abstract String fieldName(int i);
 
-    public void materializeAt(@SuppressWarnings("unused") FixedNode fixed) {
-        // nothing to do in here - this method allows subclasses to respond to materialization
-    }
+    public abstract void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount);
 
     public abstract int entryIndexForOffset(long constantOffset);
 
     public abstract Kind entryKind(int index);
 
     public abstract VirtualObjectNode duplicate();
+
+    public boolean hasIdentity() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +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 static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-
-public class BoxingEliminationPhase extends Phase {
-
-    private final MetaAccessProvider metaAccess;
-
-    public BoxingEliminationPhase(MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (graph.getNodes(UnboxNode.class).isNotEmpty()) {
-
-            Map<PhiNode, PhiNode> phiReplacements = new HashMap<>();
-            for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-                tryEliminate(graph, unboxNode, phiReplacements);
-            }
-
-            new DeadCodeEliminationPhase().apply(graph);
-
-            for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-                tryEliminate(boxNode);
-            }
-        }
-    }
-
-    private void tryEliminate(StructuredGraph graph, UnboxNode unboxNode, Map<PhiNode, PhiNode> phiReplacements) {
-        ValueNode unboxedValue = unboxedValue(unboxNode.source(), unboxNode.destinationKind(), phiReplacements);
-        if (unboxedValue != null) {
-            assert unboxedValue.kind() == unboxNode.kind();
-            unboxNode.replaceAtUsages(unboxedValue);
-            graph.removeFixed(unboxNode);
-        }
-    }
-
-    private PhiNode getReplacementPhi(PhiNode phiNode, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (!phiReplacements.containsKey(phiNode)) {
-            PhiNode result = null;
-            ObjectStamp stamp = phiNode.objectStamp();
-            if (stamp.nonNull() && stamp.isExactType()) {
-                ResolvedJavaType type = stamp.type();
-                if (type != null && type.equals(metaAccess.lookupJavaType(kind.toBoxedJavaClass()))) {
-                    StructuredGraph graph = (StructuredGraph) phiNode.graph();
-                    result = graph.add(new PhiNode(kind, phiNode.merge()));
-                    phiReplacements.put(phiNode, result);
-                    virtualizeUsages(phiNode, result, type, kind);
-                    int i = 0;
-                    for (ValueNode n : phiNode.values()) {
-                        ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements);
-                        if (unboxedValue != null) {
-                            assert unboxedValue.kind() == kind;
-                            result.addInput(unboxedValue);
-                        } else {
-                            UnboxNode unboxNode = graph.add(new UnboxNode(kind, n));
-                            FixedNode pred = phiNode.merge().phiPredecessorAt(i);
-                            graph.addBeforeFixed(pred, unboxNode);
-                            result.addInput(unboxNode);
-                        }
-                        ++i;
-                    }
-                }
-            }
-        }
-        return phiReplacements.get(phiNode);
-    }
-
-    private ValueNode unboxedValue(ValueNode n, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (n instanceof BoxNode) {
-            BoxNode boxNode = (BoxNode) n;
-            return boxNode.source();
-        } else if (n instanceof PhiNode) {
-            PhiNode phiNode = (PhiNode) n;
-            return getReplacementPhi(phiNode, kind, phiReplacements);
-        } else {
-            return null;
-        }
-    }
-
-    private static void tryEliminate(BoxNode boxNode) {
-
-        assert boxNode.objectStamp().isExactType();
-        virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind());
-
-        if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) {
-            // Elimination failed, because boxing object escapes.
-            return;
-        }
-
-        FrameState stateAfter = boxNode.stateAfter();
-        boxNode.setStateAfter(null);
-        stateAfter.safeDelete();
-
-        ((StructuredGraph) boxNode.graph()).removeFixed(boxNode);
-    }
-
-    private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) {
-        ValueNode virtualValueNode = null;
-        VirtualObjectNode virtualObjectNode = null;
-        for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
-            if (virtualValueNode == null) {
-                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, sourceKind, replacement));
-            }
-            n.replaceFirstInput(boxNode, virtualObjectNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,8 +36,9 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class CanonicalizerPhase extends Phase {
+public class CanonicalizerPhase extends BasePhase<PhaseContext> {
 
     private static final int MAX_ITERATION_PER_NODE = 10;
     private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
@@ -47,155 +48,161 @@
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
     public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
-    private final int newNodesMark;
-    private final Assumptions assumptions;
-    private final MetaAccessProvider runtime;
-    private final CustomCanonicalizer customCanonicalizer;
-    private final Iterable<Node> initWorkingSet;
-
-    private NodeWorkList workList;
-    private Tool tool;
-    private List<Node> snapshotTemp;
-
     public interface CustomCanonicalizer {
 
-        ValueNode canonicalize(Node node);
-    }
-
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) {
-        this(runtime, assumptions, null, 0, null);
-    }
-
-    /**
-     * @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(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(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-        this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
-    }
-
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-        this.newNodesMark = newNodesMark;
-        this.assumptions = assumptions;
-        this.runtime = runtime;
-        this.customCanonicalizer = customCanonicalizer;
-        this.initWorkingSet = workingSet;
-        this.snapshotTemp = new ArrayList<>();
+        ValueNode canonicalize(ValueNode node);
     }
 
     @Override
-    protected void run(StructuredGraph graph) {
-        if (initWorkingSet == null) {
-            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
-        } else {
-            workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
-            workList.addAll(initWorkingSet);
-        }
-        if (newNodesMark > 0) {
-            workList.addAll(graph.getNewNodes(newNodesMark));
-        }
-        tool = new Tool(workList, runtime, assumptions);
-        processWorkSet(graph);
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        new Instance(context.getRuntime(), context.getAssumptions()).run(graph);
     }
 
-    private void processWorkSet(StructuredGraph graph) {
-        graph.trackInputChange(new InputChangedListener() {
+    public static class Instance extends Phase {
+
+        private final int newNodesMark;
+        private final Assumptions assumptions;
+        private final MetaAccessProvider runtime;
+        private final CustomCanonicalizer customCanonicalizer;
+        private final Iterable<Node> initWorkingSet;
+
+        private NodeWorkList workList;
+        private Tool tool;
+        private List<Node> snapshotTemp;
+
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions) {
+            this(runtime, assumptions, null, 0, null);
+        }
 
-            @Override
-            public void inputChanged(Node node) {
-                workList.addAgain(node);
-            }
-        });
+        /**
+         * @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 Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, workingSet, 0, customCanonicalizer);
+        }
 
-        for (Node n : workList) {
-            processNode(n, graph);
+        /**
+         * @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 Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
+        }
+
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            super("Canonicalizer");
+            this.newNodesMark = newNodesMark;
+            this.assumptions = assumptions;
+            this.runtime = runtime;
+            this.customCanonicalizer = customCanonicalizer;
+            this.initWorkingSet = workingSet;
+            this.snapshotTemp = new ArrayList<>();
         }
 
-        graph.stopTrackingInputChange();
-    }
-
-    private void processNode(Node node, StructuredGraph graph) {
-        if (node.isAlive()) {
-            METRIC_PROCESSED_NODES.increment();
-
-            if (tryGlobalValueNumbering(node, graph)) {
-                return;
+        @Override
+        protected void run(StructuredGraph graph) {
+            if (initWorkingSet == null) {
+                workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
+            } else {
+                workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
+                workList.addAll(initWorkingSet);
+            }
+            if (newNodesMark > 0) {
+                workList.addAll(graph.getNewNodes(newNodesMark));
             }
-            int mark = graph.getMark();
-            if (!tryKillUnused(node)) {
-                node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
-                if (!tryCanonicalize(node, graph)) {
-                    tryInferStamp(node, graph);
-                } else {
-                    for (Node in : snapshotTemp) {
-                        if (in.isAlive() && in.usages().isEmpty()) {
-                            GraphUtil.killWithUnusedFloatingInputs(in);
+            tool = new Tool(workList, runtime, assumptions);
+            processWorkSet(graph);
+        }
+
+        private void processWorkSet(StructuredGraph graph) {
+            graph.trackInputChange(new InputChangedListener() {
+
+                @Override
+                public void inputChanged(Node node) {
+                    workList.addAgain(node);
+                }
+            });
+
+            for (Node n : workList) {
+                processNode(n, graph);
+            }
+
+            graph.stopTrackingInputChange();
+        }
+
+        private void processNode(Node node, StructuredGraph graph) {
+            if (node.isAlive()) {
+                METRIC_PROCESSED_NODES.increment();
+
+                if (tryGlobalValueNumbering(node, graph)) {
+                    return;
+                }
+                int mark = graph.getMark();
+                if (!tryKillUnused(node)) {
+                    node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
+                    if (!tryCanonicalize(node, graph)) {
+                        tryInferStamp(node, graph);
+                    } else {
+                        for (Node in : snapshotTemp) {
+                            if (in.isAlive() && in.usages().isEmpty()) {
+                                GraphUtil.killWithUnusedFloatingInputs(in);
+                            }
                         }
                     }
+                    snapshotTemp.clear();
                 }
-                snapshotTemp.clear();
-            }
 
-            for (Node newNode : graph.getNewNodes(mark)) {
-                workList.add(newNode);
+                for (Node newNode : graph.getNewNodes(mark)) {
+                    workList.add(newNode);
+                }
             }
         }
-    }
 
-    private static boolean tryKillUnused(Node node) {
-        if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
-            GraphUtil.killWithUnusedFloatingInputs(node);
-            return true;
-        }
-        return false;
-    }
-
-    public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
-        if (node.getNodeClass().valueNumberable()) {
-            Node newNode = graph.findDuplicate(node);
-            if (newNode != null) {
-                assert !(node instanceof FixedNode || newNode instanceof FixedNode);
-                node.replaceAtUsages(newNode);
-                node.safeDelete();
-                METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
-                Debug.log("GVN applied and new node is %1s", newNode);
+        private static boolean tryKillUnused(Node node) {
+            if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
+                GraphUtil.killWithUnusedFloatingInputs(node);
                 return true;
             }
+            return false;
         }
-        return false;
-    }
 
-    public boolean tryCanonicalize(final Node node, final StructuredGraph graph) {
-        boolean result = baseTryCanonicalize(node, graph);
-        if (!result && customCanonicalizer != null) {
-            ValueNode canonical = customCanonicalizer.canonicalize(node);
-            if (canonical == node && customCanonicalizer != null) {
-                canonical = customCanonicalizer.canonicalize(node);
+        public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
+            if (node.getNodeClass().valueNumberable()) {
+                Node newNode = graph.findDuplicate(node);
+                if (newNode != null) {
+                    assert !(node instanceof FixedNode || newNode instanceof FixedNode);
+                    node.replaceAtUsages(newNode);
+                    node.safeDelete();
+                    METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
+                    Debug.log("GVN applied and new node is %1s", newNode);
+                    return true;
+                }
             }
-            result = performReplacement(node, graph, canonical);
+            return false;
         }
-        return result;
-    }
 
-    public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) {
-        if (node instanceof Canonicalizable) {
-            assert !(node instanceof Simplifiable);
-            METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-            return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() {
+        public boolean tryCanonicalize(final Node node, final StructuredGraph graph) {
+            boolean result = baseTryCanonicalize(node, graph);
+            if (!result && customCanonicalizer != null && node instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) node;
+                ValueNode canonical = customCanonicalizer.canonicalize(valueNode);
+                result = performReplacement(node, graph, canonical);
+            }
+            return result;
+        }
 
-                public Boolean call() {
-                    ValueNode canonical = ((Canonicalizable) node).canonical(tool);
+        public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) {
+            if (node instanceof Canonicalizable) {
+                assert !(node instanceof Simplifiable);
+                METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
+                return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() {
+
+                    public Boolean call() {
+                        ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 // @formatter:off
 //     cases:                                           original node:
 //                                         |Floating|Fixed-unconnected|Fixed-connected|
@@ -211,137 +218,139 @@
 //       X: must not happen (checked with assertions)
 // @formatter:on
 
-                    return performReplacement(node, graph, canonical);
-                }
-            });
-        } else if (node instanceof Simplifiable) {
-            Debug.log("Canonicalizer: simplifying %s", node);
-            METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
-            Debug.scope("SimplifyNode", node, new Runnable() {
+                        return performReplacement(node, graph, canonical);
+                    }
+                });
+            } else if (node instanceof Simplifiable) {
+                Debug.log("Canonicalizer: simplifying %s", node);
+                METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
+                Debug.scope("SimplifyNode", node, new Runnable() {
 
-                public void run() {
-                    ((Simplifiable) node).simplify(tool);
-                }
-            });
+                    public void run() {
+                        ((Simplifiable) node).simplify(tool);
+                    }
+                });
+            }
+            return node.isDeleted();
         }
-        return node.isDeleted();
-    }
 
-    private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
-        if (canonical == node) {
-            Debug.log("Canonicalizer: work on %s", node);
-            return false;
-        } else {
-            Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
-            METRIC_CANONICALIZED_NODES.increment();
-            if (node instanceof FloatingNode) {
-                if (canonical == null) {
-                    // case 1
-                    graph.removeFloating((FloatingNode) node);
+        private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
+            if (canonical == node) {
+                Debug.log("Canonicalizer: work on %s", node);
+                return false;
+            } else {
+                Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+                METRIC_CANONICALIZED_NODES.increment();
+                if (node instanceof FloatingNode) {
+                    if (canonical == null) {
+                        // case 1
+                        graph.removeFloating((FloatingNode) node);
+                    } else {
+                        // case 2
+                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
+                                        " : replacement should be floating or fixed and connected";
+                        graph.replaceFloating((FloatingNode) node, canonical);
+                    }
                 } else {
-                    // case 2
-                    assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
-                                    " : replacement should be floating or fixed and connected";
-                    graph.replaceFloating((FloatingNode) node, canonical);
-                }
-            } else {
-                assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
+                    assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                    FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
 
-                // When removing a fixed node, new canonicalization opportunities for its successor
-                // may arise
-                assert fixedWithNext.next() != null;
-                tool.addToWorkList(fixedWithNext.next());
+                    // When removing a fixed node, new canonicalization opportunities for its
+// successor
+                    // may arise
+                    assert fixedWithNext.next() != null;
+                    tool.addToWorkList(fixedWithNext.next());
 
-                if (canonical == null) {
-                    // case 3
-                    graph.removeFixed(fixedWithNext);
-                } else if (canonical instanceof FloatingNode) {
-                    // case 4
-                    graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
-                } else {
-                    assert canonical instanceof FixedNode;
-                    if (canonical.predecessor() == null) {
-                        assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                        // case 5
-                        graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                    if (canonical == null) {
+                        // case 3
+                        graph.removeFixed(fixedWithNext);
+                    } else if (canonical instanceof FloatingNode) {
+                        // case 4
+                        graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
                     } else {
-                        assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                        // case 6
-                        node.replaceAtUsages(canonical);
-                        graph.removeFixed(fixedWithNext);
+                        assert canonical instanceof FixedNode;
+                        if (canonical.predecessor() == null) {
+                            assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                            // case 5
+                            graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                        } else {
+                            assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                            // case 6
+                            node.replaceAtUsages(canonical);
+                            graph.removeFixed(fixedWithNext);
+                        }
                     }
                 }
+                return true;
             }
-            return true;
         }
-    }
 
-    /**
-     * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that
-     * the stamp has changed), re-queues the node's usages . If the stamp has changed then this
-     * method also checks if the stamp now describes a constant integer value, in which case the
-     * node is replaced with a constant.
-     */
-    private void tryInferStamp(Node node, StructuredGraph graph) {
-        if (node.isAlive() && node instanceof ValueNode) {
-            ValueNode valueNode = (ValueNode) node;
-            METRIC_INFER_STAMP_CALLED.increment();
-            if (valueNode.inferStamp()) {
-                METRIC_STAMP_CHANGED.increment();
-                if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
-                    ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
-                    Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
-                    valueNode.replaceAtUsages(replacement);
-                } else {
-                    for (Node usage : valueNode.usages()) {
-                        workList.addAgain(usage);
+        /**
+         * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means
+         * that the stamp has changed), re-queues the node's usages . If the stamp has changed then
+         * this method also checks if the stamp now describes a constant integer value, in which
+         * case the node is replaced with a constant.
+         */
+        private void tryInferStamp(Node node, StructuredGraph graph) {
+            if (node.isAlive() && node instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) node;
+                METRIC_INFER_STAMP_CALLED.increment();
+                if (valueNode.inferStamp()) {
+                    METRIC_STAMP_CHANGED.increment();
+                    if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
+                        ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
+                        Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
+                        valueNode.replaceAtUsages(replacement);
+                    } else {
+                        for (Node usage : valueNode.usages()) {
+                            workList.addAgain(usage);
+                        }
                     }
                 }
             }
         }
-    }
 
-    private static final class Tool implements SimplifierTool {
+        private static final class Tool implements SimplifierTool {
 
-        private final NodeWorkList nodeWorkSet;
-        private final MetaAccessProvider runtime;
-        private final Assumptions assumptions;
+            private final NodeWorkList nodeWorkSet;
+            private final MetaAccessProvider runtime;
+            private final Assumptions assumptions;
 
-        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
-            this.nodeWorkSet = nodeWorkSet;
-            this.runtime = runtime;
-            this.assumptions = assumptions;
-        }
+            public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
+                this.nodeWorkSet = nodeWorkSet;
+                this.runtime = runtime;
+                this.assumptions = assumptions;
+            }
 
-        @Override
-        public void deleteBranch(FixedNode branch) {
-            branch.predecessor().replaceFirstSuccessor(branch, null);
-            GraphUtil.killCFG(branch);
-        }
+            @Override
+            public void deleteBranch(FixedNode branch) {
+                branch.predecessor().replaceFirstSuccessor(branch, null);
+                GraphUtil.killCFG(branch);
+            }
 
-        /**
-         * @return an object that can be used for recording assumptions or {@code null} if
-         *         assumptions are not allowed in the current context.
-         */
-        @Override
-        public Assumptions assumptions() {
-            return assumptions;
-        }
+            /**
+             * @return an object that can be used for recording assumptions or {@code null} if
+             *         assumptions are not allowed in the current context.
+             */
+            @Override
+            public Assumptions assumptions() {
+                return assumptions;
+            }
 
-        @Override
-        public MetaAccessProvider runtime() {
-            return runtime;
-        }
+            @Override
+            public MetaAccessProvider runtime() {
+                return runtime;
+            }
 
-        @Override
-        public void addToWorkList(Node node) {
-            nodeWorkSet.addAgain(node);
-        }
+            @Override
+            public void addToWorkList(Node node) {
+                nodeWorkSet.addAgain(node);
+            }
 
-        @Override
-        public void removeIfUnused(Node node) {
-            tryKillUnused(node);
+            @Override
+            public void removeIfUnused(Node node) {
+                tryKillUnused(node);
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -346,7 +346,7 @@
         private static Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
             Scope parent = processedLoops.get(loop.parent);
             if (parent == null) {
-                parent = createScope(loop, processedLoops);
+                parent = createScope(loop.parent, processedLoops);
             }
             Scope result = new Scope(loop.loopBegin(), parent);
             processedLoops.put(loop, result);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -482,9 +482,9 @@
                     PiNode piNode;
                     if (isNull) {
                         ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph);
-                        piNode = graph.unique(new PiNode(nullObject, anchor, StampFactory.forConstant(nullObject.value, metaAccessProvider)));
+                        piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), anchor));
                     } else {
-                        piNode = graph.unique(new PiNode(object, anchor, StampFactory.declared(type, nonNull)));
+                        piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), anchor));
                     }
                     checkCast.replaceAtUsages(piNode);
                     graph.replaceFixedWithFixed(checkCast, anchor);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandBoxingNodesPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-
-public class ExpandBoxingNodesPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public ExpandBoxingNodesPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-            boxNode.expand(pool);
-        }
-
-        for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-            unboxNode.expand(pool);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -146,7 +146,7 @@
             StructuredGraph graph = (StructuredGraph) accessNode.graph();
             assert accessNode.getNullCheck() == false;
             Object locationIdentity = accessNode.location().locationIdentity();
-            if (locationIdentity != LocationNode.UNKNOWN_LOCATION) {
+            if (locationIdentity != LocationNode.ANY_LOCATION) {
                 ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
                 FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess);
                 floatingNode.setNullCheck(accessNode.getNullCheck());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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 com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
+
+public class FrameStateAssignmentPhase extends Phase {
+
+    private static class FrameStateAssignmentState {
+
+        private FrameState framestate;
+
+        public FrameStateAssignmentState(FrameState framestate) {
+            this.framestate = framestate;
+        }
+
+        public FrameState getFramestate() {
+            return framestate;
+        }
+
+        public void setFramestate(FrameState framestate) {
+            assert framestate != null;
+            this.framestate = framestate;
+        }
+
+        @Override
+        public String toString() {
+            return "FrameStateAssignementState: " + framestate;
+        }
+    }
+
+    private static class FrameStateAssignementClosure extends BlockIteratorClosure<FrameStateAssignmentState> {
+
+        @Override
+        protected void processBlock(Block block, FrameStateAssignmentState currentState) {
+            FixedNode node = block.getBeginNode();
+            while (node != null) {
+                if (node instanceof DeoptimizingNode) {
+                    DeoptimizingNode deopt = (DeoptimizingNode) node;
+                    if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+                        deopt.setDeoptimizationState(currentState.getFramestate());
+                    }
+                }
+
+                if (node instanceof StateSplit) {
+                    StateSplit stateSplit = (StateSplit) node;
+                    if (stateSplit.stateAfter() != null) {
+                        currentState.setFramestate(stateSplit.stateAfter());
+                        stateSplit.setStateAfter(null);
+                    }
+                }
+
+                if (node instanceof FixedWithNextNode) {
+                    node = ((FixedWithNextNode) node).next();
+                } else {
+                    node = null;
+                }
+            }
+        }
+
+        @Override
+        protected FrameStateAssignmentState merge(Block mergeBlock, List<FrameStateAssignmentState> states) {
+            MergeNode merge = (MergeNode) mergeBlock.getBeginNode();
+            if (merge.stateAfter() != null) {
+                return new FrameStateAssignmentState(merge.stateAfter());
+            }
+            return new FrameStateAssignmentState(singleFrameState(states));
+        }
+
+        @Override
+        protected FrameStateAssignmentState cloneState(FrameStateAssignmentState oldState) {
+            return new FrameStateAssignmentState(oldState.getFramestate());
+        }
+
+        @Override
+        protected List<FrameStateAssignmentState> processLoop(Loop loop, FrameStateAssignmentState initialState) {
+            return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
+        }
+
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        assert checkFixedDeopts(graph);
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+        ReentrantBlockIterator.apply(new FrameStateAssignementClosure(), cfg.getStartBlock(), new FrameStateAssignmentState(null), null);
+    }
+
+    private static boolean checkFixedDeopts(StructuredGraph graph) {
+        NodePredicate isFloatingNode = GraphUtil.isFloatingNode();
+        for (Node n : graph.getNodes().filterInterface(DeoptimizingNode.class)) {
+            if (((DeoptimizingNode) n).canDeoptimize() && isFloatingNode.apply(n)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static FrameState singleFrameState(List<FrameStateAssignmentState> states) {
+        Iterator<FrameStateAssignmentState> it = states.iterator();
+        assert it.hasNext();
+        FrameState first = it.next().getFramestate();
+        while (it.hasNext()) {
+            if (first != it.next().getFramestate()) {
+                return null;
+            }
+        }
+        return first;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -114,12 +114,12 @@
                 Access fixedAccess = access;
                 if (access instanceof FloatingAccessNode) {
                     fixedAccess = ((FloatingAccessNode) access).asFixedNode();
-                    replaceCurrent((FixedWithNextNode) fixedAccess.node());
+                    replaceCurrent((FixedWithNextNode) fixedAccess.asNode());
                 }
                 assert fixedAccess instanceof FixedNode;
                 fixedAccess.setNullCheck(true);
                 LogicNode condition = guard.condition();
-                guard.replaceAndDelete(fixedAccess.node());
+                guard.replaceAndDelete(fixedAccess.asNode());
                 if (condition.usages().isEmpty()) {
                     GraphUtil.killWithUnusedFloatingInputs(condition);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IdentifyBoxingPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +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 java.lang.reflect.*;
-
-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.java.*;
-import com.oracle.graal.phases.*;
-
-public class IdentifyBoxingPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public IdentifyBoxingPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Invoke invoke : graph.getInvokes()) {
-            tryIntrinsify(invoke);
-        }
-    }
-
-    public void tryIntrinsify(Invoke invoke) {
-        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
-            return;
-        }
-        MethodCallTargetNode callTarget = invoke.methodCallTarget();
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        if (pool.isSpecialMethod(targetMethod)) {
-            assert callTarget.arguments().size() == 1 : "boxing/unboxing method must have exactly one argument";
-            Kind returnKind = callTarget.returnKind();
-            ValueNode sourceValue = callTarget.arguments().get(0);
-
-            // Check whether this is a boxing or an unboxing.
-            Node newNode = null;
-            if (returnKind == Kind.Object) {
-                // We have a boxing method here.
-                assert Modifier.isStatic(targetMethod.getModifiers()) : "boxing method must be static";
-                Kind sourceKind = targetMethod.getSignature().getParameterKind(0);
-                newNode = invoke.graph().add(new BoxNode(sourceValue, targetMethod.getDeclaringClass(), sourceKind, invoke.bci()));
-            } else {
-                // We have an unboxing method here.
-                assert !Modifier.isStatic(targetMethod.getModifiers()) : "unboxing method must be an instance method";
-                newNode = invoke.graph().add(new UnboxNode(returnKind, sourceValue));
-            }
-
-            // Intrinsify the invoke to the special node.
-            invoke.intrinsify(newNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -52,6 +52,7 @@
 
     private final MetaAccessProvider runtime;
     private final Assumptions assumptions;
+    private final Replacements replacements;
     private final GraphCache cache;
     private final InliningPolicy inliningPolicy;
     private final OptimisticOptimizations optimisticOpts;
@@ -67,12 +68,15 @@
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
     private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
 
-    public InliningPhase(MetaAccessProvider runtime, Map<Invoke, Double> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
-        this(runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts);
+    public InliningPhase(MetaAccessProvider runtime, Map<Invoke, Double> hints, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan,
+                    OptimisticOptimizations optimisticOpts) {
+        this(runtime, replacements, assumptions, cache, plan, createInliningPolicy(runtime, replacements, assumptions, optimisticOpts, hints), optimisticOpts);
     }
 
-    public InliningPhase(MetaAccessProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) {
+    public InliningPhase(MetaAccessProvider runtime, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy,
+                    OptimisticOptimizations optimisticOpts) {
         this.runtime = runtime;
+        this.replacements = replacements;
         this.assumptions = assumptions;
         this.cache = cache;
         this.plan = plan;
@@ -107,13 +111,13 @@
                 if (isWorthInlining) {
                     int mark = graph.getMark();
                     try {
-                        List<Node> invokeUsages = candidate.invoke().node().usages().snapshot();
-                        candidate.inline(graph, runtime, this, assumptions);
+                        List<Node> invokeUsages = candidate.invoke().asNode().usages().snapshot();
+                        candidate.inline(graph, runtime, replacements, this, assumptions);
                         Debug.dump(graph, "after %s", candidate);
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
                         inliningPolicy.scanInvokes(newNodes);
                         if (GraalOptions.OptCanonicalizer) {
-                            new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
+                            new CanonicalizerPhase.Instance(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         inliningCount++;
                         metricInliningPerformed.increment();
@@ -157,7 +161,7 @@
                     new ComputeProbabilityPhase().apply(newGraph);
                 }
                 if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(runtime, assumptions).apply(newGraph);
+                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
                 }
                 if (GraalOptions.CullFrameStates) {
                     new CullFrameStatesPhase().apply(newGraph);
@@ -178,10 +182,12 @@
     private static class GreedySizeBasedInliningDecision implements InliningDecision {
 
         private final MetaAccessProvider runtime;
+        private final Replacements replacements;
         private final Map<Invoke, Double> hints;
 
-        public GreedySizeBasedInliningDecision(MetaAccessProvider runtime, Map<Invoke, Double> hints) {
+        public GreedySizeBasedInliningDecision(MetaAccessProvider runtime, Replacements replacements, Map<Invoke, Double> hints) {
             this.runtime = runtime;
+            this.replacements = replacements;
             this.hints = hints;
         }
 
@@ -195,8 +201,14 @@
              * also getting queued in the compilation queue concurrently)
              */
 
-            if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) {
-                return InliningUtil.logInlinedMethod(info, "intrinsic");
+            if (GraalOptions.AlwaysInlineIntrinsics) {
+                if (onlyIntrinsics(replacements, info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
+            } else {
+                if (onlyForcedIntrinsics(replacements, info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
             }
 
             double bonus = 1;
@@ -266,7 +278,7 @@
         private static int countInvokeUsages(InlineInfo info) {
             // inlining calls with lots of usages simplifies the caller
             int usages = 0;
-            for (Node n : info.invoke().node().usages()) {
+            for (Node n : info.invoke().asNode().usages()) {
                 if (!(n instanceof FrameState)) {
                     usages++;
                 }
@@ -334,9 +346,21 @@
             return result;
         }
 
-        private static boolean onlyIntrinsics(InlineInfo info) {
+        private static boolean onlyIntrinsics(Replacements replacements, InlineInfo info) {
             for (int i = 0; i < info.numberOfMethods(); i++) {
-                if (!InliningUtil.canIntrinsify(info.methodAt(i))) {
+                if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static boolean onlyForcedIntrinsics(Replacements replacements, InlineInfo info) {
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i))) {
+                    return false;
+                }
+                if (!replacements.isForcedSubstitution(info.methodAt(i))) {
                     return false;
                 }
             }
@@ -348,13 +372,15 @@
 
         private final InliningDecision inliningDecision;
         private final Assumptions assumptions;
+        private final Replacements replacements;
         private final OptimisticOptimizations optimisticOpts;
         private final Deque<Invoke> sortedInvokes;
         private NodeBitMap visitedFixedNodes;
         private FixedNode invokePredecessor;
 
-        public CFInliningPolicy(InliningDecision inliningPolicy, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
+        public CFInliningPolicy(InliningDecision inliningPolicy, Replacements replacements, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
             this.inliningDecision = inliningPolicy;
+            this.replacements = replacements;
             this.assumptions = assumptions;
             this.optimisticOpts = optimisticOpts;
             this.sortedInvokes = new ArrayDeque<>();
@@ -372,7 +398,7 @@
 
         public InlineInfo next() {
             Invoke invoke = sortedInvokes.pop();
-            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, optimisticOpts);
+            InlineInfo info = InliningUtil.getInlineInfo(invoke, replacements, assumptions, optimisticOpts);
             if (info != null) {
                 invokePredecessor = (FixedNode) info.invoke().predecessor();
                 assert invokePredecessor.isAlive();
@@ -513,8 +539,8 @@
         }
     }
 
-    private static InliningPolicy createInliningPolicy(MetaAccessProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Map<Invoke, Double> hints) {
-        InliningDecision inliningDecision = new GreedySizeBasedInliningDecision(runtime, hints);
-        return new CFInliningPolicy(inliningDecision, assumptions, optimisticOpts);
+    private static InliningPolicy createInliningPolicy(MetaAccessProvider runtime, Replacements replacements, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Map<Invoke, Double> hints) {
+        InliningDecision inliningDecision = new GreedySizeBasedInliningDecision(runtime, replacements, hints);
+        return new CFInliningPolicy(inliningDecision, replacements, assumptions, optimisticOpts);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 15 08:51:19 2013 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -39,6 +38,7 @@
 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.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -73,13 +73,47 @@
         boolean isWorthInlining(InlineInfo info);
     }
 
+    /**
+     * Print a HotSpot-style inlining message to the console.
+     */
+    private static void printInlining(final InlineInfo info, final boolean success, final String msg, final Object... args) {
+        printInlining(info.methodAt(0), info.invoke(), success, msg, args);
+    }
+
+    /**
+     * Print a HotSpot-style inlining message to the console.
+     */
+    private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final boolean success, final String msg, final Object... args) {
+        if (GraalOptions.HotSpotPrintInlining) {
+            final int mod = method.getModifiers();
+            // 1234567
+            TTY.print("        ");     // print timestamp
+            // 1234
+            TTY.print("     ");        // print compilation number
+            // % s ! b n
+            TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ');
+            TTY.print("     ");        // more indent
+            TTY.print("    ");         // initial inlining indent
+            final int level = computeInliningLevel(invoke);
+            for (int i = 0; i < level; i++) {
+                TTY.print("  ");
+            }
+            TTY.println(String.format("@ %d  %s   %s%s", invoke.bci(), methodName(method, null), success ? "" : "not inlining ", String.format(msg, args)));
+        }
+    }
+
+    public static boolean logInlinedMethod(InlineInfo info, String msg, Object... args) {
+        logInliningDecision(info, true, msg, args);
+        return true;
+    }
+
     public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) {
-
         logInliningDecision(info, false, msg, args);
         return false;
     }
 
     public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) {
+        printInlining(info, success, msg, args);
         if (shouldLogInliningDecision()) {
             logInliningDecision(methodName(info), success, msg, args);
         }
@@ -94,11 +128,6 @@
         });
     }
 
-    public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) {
-        logInliningDecision(info, true, string, args);
-        return true;
-    }
-
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) {
         if (shouldLogInliningDecision()) {
             String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName());
@@ -112,6 +141,7 @@
     }
 
     private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg, Object... args) {
+        printInlining(method, invoke, false, msg, args);
         if (shouldLogInliningDecision()) {
             String methodString = methodName(method, invoke);
             logInliningDecision(methodString, false, msg, args);
@@ -120,6 +150,7 @@
     }
 
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, ResolvedJavaMethod method, String msg) {
+        printInlining(method, invoke, false, msg, new Object[0]);
         if (shouldLogInliningDecision()) {
             String methodString = methodName(method, invoke);
             logInliningDecision(methodString, false, msg, new Object[0]);
@@ -193,7 +224,7 @@
          * return value of the inlined method (or null for void methods and methods that have no
          * non-exceptional exit).
          **/
-        void inline(StructuredGraph graph, MetaAccessProvider runtime, InliningCallback callback, Assumptions assumptions);
+        void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions);
 
         /**
          * Try to make the call static bindable to avoid interface and virtual method calls.
@@ -219,17 +250,17 @@
             return computeInliningLevel(invoke);
         }
 
-        protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, InliningCallback callback, Assumptions assumptions, boolean receiverNullCheck) {
-            Class<? extends FixedWithNextNode> macroNodeClass = getMacroNodeClass(concrete);
+        protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, InliningCallback callback, Replacements replacements, Assumptions assumptions, boolean receiverNullCheck) {
+            Class<? extends FixedWithNextNode> macroNodeClass = getMacroNodeClass(replacements, concrete);
             StructuredGraph graph = (StructuredGraph) invoke.graph();
             if (macroNodeClass != null) {
                 FixedWithNextNode macroNode;
                 try {
                     macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
                 } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
-                    throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass);
+                    throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
                 }
-                macroNode.setProbability(invoke.node().probability());
+                macroNode.setProbability(invoke.asNode().probability());
                 CallTargetNode callTarget = invoke.callTarget();
                 if (invoke instanceof InvokeNode) {
                     graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
@@ -240,7 +271,7 @@
                 }
                 GraphUtil.killWithUnusedFloatingInputs(callTarget);
             } else {
-                StructuredGraph calleeGraph = getIntrinsicGraph(concrete);
+                StructuredGraph calleeGraph = getIntrinsicGraph(replacements, concrete);
                 if (calleeGraph == null) {
                     calleeGraph = getGraph(concrete, callback);
                 }
@@ -268,7 +299,7 @@
         protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
             MethodCallTargetNode oldCallTarget = invoke.methodCallTarget();
             MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
-            invoke.node().replaceFirstInput(oldCallTarget, newCallTarget);
+            invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget);
         }
     }
 
@@ -286,8 +317,8 @@
         }
 
         @Override
-        public void inline(StructuredGraph compilerGraph, MetaAccessProvider runtime, InliningCallback callback, Assumptions assumptions) {
-            inline(invoke, concrete, callback, assumptions, true);
+        public void inline(StructuredGraph compilerGraph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) {
+            inline(invoke, concrete, callback, replacements, assumptions, true);
         }
 
         @Override
@@ -340,9 +371,9 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, MetaAccessProvider runtime, InliningCallback callback, Assumptions assumptions) {
+        public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) {
             createGuard(graph, runtime);
-            inline(invoke, concrete, callback, assumptions, false);
+            inline(invoke, concrete, callback, replacements, assumptions, false);
         }
 
         @Override
@@ -364,9 +395,9 @@
             ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-            graph.addBeforeFixed(invoke.node(), guard);
-            graph.addBeforeFixed(invoke.node(), anchor);
+            graph.addBeforeFixed(invoke.asNode(), receiverHub);
+            graph.addBeforeFixed(invoke.asNode(), guard);
+            graph.addBeforeFixed(invoke.asNode(), anchor);
         }
 
         @Override
@@ -410,13 +441,13 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, MetaAccessProvider runtime, InliningCallback callback, Assumptions assumptions) {
+        public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) {
             // receiver null check must be the first node
             InliningUtil.receiverNullCheck(invoke);
             if (hasSingleMethod()) {
-                inlineSingleMethod(graph, callback, assumptions);
+                inlineSingleMethod(graph, callback, replacements, assumptions);
             } else {
-                inlineMultipleMethods(graph, callback, assumptions);
+                inlineMultipleMethods(graph, callback, replacements, assumptions);
             }
         }
 
@@ -428,7 +459,7 @@
             return notRecordedTypeProbability > 0;
         }
 
-        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) {
+        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions) {
             int numberOfMethods = concretes.size();
             FixedNode continuation = invoke.next();
 
@@ -439,8 +470,8 @@
             returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
 
             PhiNode returnValuePhi = null;
-            if (invoke.node().kind() != Kind.Void) {
-                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
+            if (invoke.asNode().kind() != Kind.Void) {
+                returnValuePhi = graph.unique(new PhiNode(invoke.asNode().kind(), returnMerge));
             }
 
             MergeNode exceptionMerge = null;
@@ -489,7 +520,7 @@
                 GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
             }
 
-            assert invoke.node().isAlive();
+            assert invoke.asNode().isAlive();
 
             // replace the invoke with a switch on the type of the actual receiver
             createDispatchOnTypeBeforeInvoke(graph, successors, false);
@@ -497,10 +528,10 @@
             assert invoke.next() == continuation;
             invoke.setNext(null);
             returnMerge.setNext(continuation);
-            invoke.node().replaceAtUsages(returnValuePhi);
-            invoke.node().replaceAndDelete(null);
+            invoke.asNode().replaceAtUsages(returnValuePhi);
+            invoke.asNode().replaceAndDelete(null);
 
-            ArrayList<PiNode> replacements = new ArrayList<>();
+            ArrayList<PiNode> replacementNodes = new ArrayList<>();
 
             // do the actual inlining for every invoke
             for (int i = 0; i < numberOfMethods; i++) {
@@ -513,12 +544,12 @@
                 PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver, exact);
                 invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
-                inline(invokeForInlining, concretes.get(i), callback, assumptions, false);
+                inline(invokeForInlining, concretes.get(i), callback, replacements, assumptions, false);
 
-                replacements.add(anchoredReceiver);
+                replacementNodes.add(anchoredReceiver);
             }
             if (shouldFallbackToInvoke()) {
-                replacements.add(null);
+                replacementNodes.add(null);
             }
             if (GraalOptions.OptTailDuplication) {
                 /*
@@ -538,7 +569,7 @@
                 if (opportunities > 0) {
                     metricInliningTailDuplication.increment();
                     Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
-                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacements);
+                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes);
                 }
             }
         }
@@ -576,7 +607,7 @@
             return result;
         }
 
-        private void inlineSingleMethod(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) {
+        private void inlineSingleMethod(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions) {
             assert concretes.size() == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
             BeginNode calleeEntryNode = graph.add(new BeginNode());
@@ -586,10 +617,10 @@
             BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, false);
 
-            calleeEntryNode.setNext(invoke.node());
+            calleeEntryNode.setNext(invoke.asNode());
 
             ResolvedJavaMethod concrete = concretes.get(0);
-            inline(invoke, concrete, callback, assumptions, false);
+            inline(invoke, concrete, callback, replacements, assumptions, false);
         }
 
         private void createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor) {
@@ -597,7 +628,7 @@
 
             Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
             LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind));
-            graph.addBeforeFixed(invoke.node(), hub);
+            graph.addBeforeFixed(invoke.asNode(), hub);
 
             ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()];
             double[] keyProbabilities = new double[ptypes.size() + 1];
@@ -612,7 +643,7 @@
             keySuccessors[keySuccessors.length - 1] = successors.length - 1;
 
             TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
-            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
+            FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor();
             pred.setNext(typeSwitch);
         }
 
@@ -620,7 +651,7 @@
                         double probability, boolean useForInlining) {
             Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability);
             BeginNode calleeEntryNode = graph.add(new BeginNode());
-            calleeEntryNode.setNext(duplicatedInvoke.node());
+            calleeEntryNode.setNext(duplicatedInvoke.asNode());
             calleeEntryNode.setProbability(probability);
 
             EndNode endNode = graph.add(new EndNode());
@@ -630,24 +661,24 @@
             returnMerge.addForwardEnd(endNode);
 
             if (returnValuePhi != null) {
-                returnValuePhi.addInput(duplicatedInvoke.node());
+                returnValuePhi.addInput(duplicatedInvoke.asNode());
             }
             return calleeEntryNode;
         }
 
         private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) {
-            Invoke result = (Invoke) invoke.node().copyWithInputs();
+            Invoke result = (Invoke) invoke.asNode().copyWithInputs();
             Node callTarget = result.callTarget().copyWithInputs();
-            result.node().replaceFirstInput(result.callTarget(), callTarget);
+            result.asNode().replaceFirstInput(result.callTarget(), callTarget);
             result.setUseForInlining(useForInlining);
             result.setProbability(probability);
             result.setInliningRelevance(invoke.inliningRelevance() * probability);
 
-            Kind kind = invoke.node().kind();
+            Kind kind = invoke.asNode().kind();
             if (kind != Kind.Void) {
                 FrameState stateAfter = invoke.stateAfter();
                 stateAfter = stateAfter.duplicate(stateAfter.bci);
-                stateAfter.replaceFirstInput(invoke.node(), result.node());
+                stateAfter.replaceFirstInput(invoke.asNode(), result.asNode());
                 result.setStateAfter(stateAfter);
             }
 
@@ -712,7 +743,7 @@
             BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, true);
 
-            invocationEntry.setNext(invoke.node());
+            invocationEntry.setNext(invoke.asNode());
             ValueNode receiver = invoke.methodCallTarget().receiver();
             PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
@@ -759,11 +790,11 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, MetaAccessProvider runtime, InliningCallback callback, Assumptions assumptions) {
+        public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) {
             assumptions.record(takenAssumption);
             Debug.log("recording assumption: %s", takenAssumption);
 
-            super.inline(graph, runtime, callback, assumptions);
+            super.inline(graph, runtime, replacements, callback, assumptions);
         }
 
         @Override
@@ -784,7 +815,7 @@
      * @param invoke the invoke that should be inlined
      * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke
      */
-    public static InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
+    public static InlineInfo getInlineInfo(Invoke invoke, Replacements replacements, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
         if (!checkInvokeConditions(invoke)) {
             return null;
         }
@@ -793,7 +824,7 @@
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
 
         if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
-            return getExactInlineInfo(invoke, optimisticOpts, targetMethod);
+            return getExactInlineInfo(replacements, invoke, optimisticOpts, targetMethod);
         }
 
         assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
@@ -808,49 +839,50 @@
                 holder = receiverType;
                 if (receiverStamp.isExactType()) {
                     assert targetMethod.getDeclaringClass().isAssignableFrom(holder) : holder + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod;
-                    return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod));
+                    return getExactInlineInfo(replacements, invoke, optimisticOpts, holder.resolveMethod(targetMethod));
                 }
             }
         }
 
         if (holder.isArray()) {
             // arrays can be treated as Objects
-            return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod));
+            return getExactInlineInfo(replacements, invoke, optimisticOpts, holder.resolveMethod(targetMethod));
         }
 
         if (assumptions.useOptimisticAssumptions()) {
             ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                return getAssumptionInlineInfo(invoke, optimisticOpts, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
+                return getAssumptionInlineInfo(replacements, invoke, optimisticOpts, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
             }
 
             ResolvedJavaMethod concrete = holder.findUniqueConcreteMethod(targetMethod);
             if (concrete != null) {
-                return getAssumptionInlineInfo(invoke, optimisticOpts, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete));
+                return getAssumptionInlineInfo(replacements, invoke, optimisticOpts, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete));
             }
         }
 
         // type check based inlining
-        return getTypeCheckedInlineInfo(invoke, caller, holder, targetMethod, optimisticOpts);
+        return getTypeCheckedInlineInfo(replacements, invoke, caller, holder, targetMethod, optimisticOpts);
     }
 
-    private static InlineInfo getAssumptionInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) {
+    private static InlineInfo getAssumptionInlineInfo(Replacements replacements, Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) {
         assert !Modifier.isAbstract(concrete.getModifiers());
-        if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
+        if (!checkTargetConditions(replacements, invoke, concrete, optimisticOpts)) {
             return null;
         }
         return new AssumptionInlineInfo(invoke, concrete, takenAssumption);
     }
 
-    private static InlineInfo getExactInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) {
+    private static InlineInfo getExactInlineInfo(Replacements replacements, Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) {
         assert !Modifier.isAbstract(targetMethod.getModifiers());
-        if (!checkTargetConditions(invoke, targetMethod, optimisticOpts)) {
+        if (!checkTargetConditions(replacements, invoke, targetMethod, optimisticOpts)) {
             return null;
         }
         return new ExactInlineInfo(invoke, targetMethod);
     }
 
-    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts) {
+    private static InlineInfo getTypeCheckedInlineInfo(Replacements replacements, Invoke invoke, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod,
+                    OptimisticOptimizations optimisticOpts) {
         ProfilingInfo profilingInfo = caller.getProfilingInfo();
         JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
         if (typeProfile == null) {
@@ -871,7 +903,7 @@
 
             ResolvedJavaType type = ptypes.get(0).getType();
             ResolvedJavaMethod concrete = type.resolveMethod(targetMethod);
-            if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
+            if (!checkTargetConditions(replacements, invoke, concrete, optimisticOpts)) {
                 return null;
             }
             return new TypeGuardInlineInfo(invoke, concrete, type);
@@ -903,7 +935,7 @@
             }
 
             for (ResolvedJavaMethod concrete : concreteMethods) {
-                if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
+                if (!checkTargetConditions(replacements, invoke, concrete, optimisticOpts)) {
                     return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
                 }
             }
@@ -930,11 +962,11 @@
 
     private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver, boolean exact) {
         // to avoid that floating reads on receiver fields float above the type check
-        return graph.unique(new PiNode(receiver, anchor, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType)));
+        return graph.unique(new PiNode(receiver, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType), anchor));
     }
 
     private static boolean checkInvokeConditions(Invoke invoke) {
-        if (invoke.predecessor() == null || !invoke.node().isAlive()) {
+        if (invoke.predecessor() == null || !invoke.asNode().isAlive()) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
         } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node");
@@ -951,10 +983,10 @@
         }
     }
 
-    private static boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
+    private static boolean checkTargetConditions(Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "the method is not resolved");
-        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(method))) {
+        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(replacements, method))) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it is a non-intrinsic native method");
         } else if (Modifier.isAbstract(method.getModifiers())) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it is an abstract method");
@@ -1016,7 +1048,7 @@
      */
     public static Map<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        StructuredGraph graph = (StructuredGraph) invoke.node().graph();
+        StructuredGraph graph = (StructuredGraph) invoke.asNode().graph();
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter.isAlive();
@@ -1044,17 +1076,17 @@
             }
         }
         // ensure proper anchoring of things that were anchored to the StartNode
-        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node()));
+        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.asNode()));
 
-        assert invoke.node().successors().first() != null : invoke;
-        assert invoke.node().predecessor() != null;
+        assert invoke.asNode().successors().first() != null : invoke;
+        assert invoke.asNode().predecessor() != null;
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
         if (receiverNullCheck) {
             receiverNullCheck(invoke);
         }
-        invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate);
+        invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
@@ -1093,7 +1125,7 @@
         }
 
         FrameState outerFrameState = null;
-        double invokeProbability = invoke.node().probability();
+        double invokeProbability = invoke.asNode().probability();
         int callerLockDepth = stateAfter.nestedLockDepth();
         for (Node node : duplicates.values()) {
             if (GraalOptions.ProbabilityAnalysis) {
@@ -1116,7 +1148,7 @@
             }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
-                assert frameState.bci != FrameState.BEFORE_BCI;
+                assert frameState.bci != FrameState.BEFORE_BCI : frameState;
                 if (frameState.bci == FrameState.AFTER_BCI) {
                     frameState.replaceAndDelete(stateAfter);
                 } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
@@ -1131,7 +1163,7 @@
                     if (frameState.outerFrameState() == null) {
                         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 = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind());
                             outerFrameState.setDuringCall(true);
                         }
                         frameState.setOuterFrameState(outerFrameState);
@@ -1151,7 +1183,7 @@
             } else {
                 returnValue = duplicates.get(returnNode.result());
             }
-            invoke.node().replaceAtUsages(returnValue);
+            invoke.asNode().replaceAtUsages(returnValue);
             Node returnDuplicate = duplicates.get(returnNode);
             returnDuplicate.clearInputs();
             Node n = invoke.next();
@@ -1159,8 +1191,8 @@
             returnDuplicate.replaceAndDelete(n);
         }
 
-        invoke.node().replaceAtUsages(null);
-        GraphUtil.killCFG(invoke.node());
+        invoke.asNode().replaceAtUsages(null);
+        GraphUtil.killCFG(invoke.asNode());
 
         return duplicates;
     }
@@ -1171,21 +1203,20 @@
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
         if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
-            graph.addBeforeFixed(invoke.node(),
+            graph.addBeforeFixed(invoke.asNode(),
                             graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)));
         }
     }
 
-    public static boolean canIntrinsify(ResolvedJavaMethod target) {
-        return getIntrinsicGraph(target) != null || getMacroNodeClass(target) != null;
+    public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target) {
+        return getIntrinsicGraph(replacements, target) != null || getMacroNodeClass(replacements, target) != null;
     }
 
-    public static StructuredGraph getIntrinsicGraph(ResolvedJavaMethod target) {
-        return (StructuredGraph) target.getCompilerStorage().get(MethodSubstitution.class);
+    public static StructuredGraph getIntrinsicGraph(Replacements replacements, ResolvedJavaMethod target) {
+        return replacements.getMethodSubstitution(target);
     }
 
-    public static Class<? extends FixedWithNextNode> getMacroNodeClass(ResolvedJavaMethod target) {
-        Object result = target.getCompilerStorage().get(Node.class);
-        return result == null ? null : ((Class<?>) result).asSubclass(FixedWithNextNode.class);
+    public static Class<? extends FixedWithNextNode> getMacroNodeClass(Replacements replacements, ResolvedJavaMethod target) {
+        return replacements.getMacroSubstitution(target);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -53,7 +53,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -65,6 +65,11 @@
         }
 
         @Override
+        public Replacements getReplacements() {
+            return replacements;
+        }
+
+        @Override
         public ValueNode createNullCheckGuard(ValueNode object) {
             return createGuard(object.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
         }
@@ -113,13 +118,15 @@
 
     private final TargetDescription target;
     private final GraalCodeCacheProvider runtime;
+    private final Replacements replacements;
     private final Assumptions assumptions;
 
     private boolean deferred;
 
-    public LoweringPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+    public LoweringPhase(TargetDescription target, GraalCodeCacheProvider runtime, Replacements replacements, Assumptions assumptions) {
         this.target = target;
         this.runtime = runtime;
+        this.replacements = replacements;
         this.assumptions = assumptions;
     }
 
@@ -144,7 +151,7 @@
             deferred = false;
             processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
             Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
 
             if (!deferred && !containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.phases.common;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+
+public class PushThroughPiPhase extends Phase {
+
+    public static final DebugMetric PUSHED_NODES = Debug.metric("NodesPushedThroughPi");
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (PiNode pi : graph.getNodes(PiNode.class)) {
+            for (Node n : pi.usages().snapshot()) {
+                if (n instanceof PiPushable) {
+                    PiPushable pip = (PiPushable) n;
+                    if (pip.push(pi)) {
+                        PUSHED_NODES.add(1);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -46,7 +46,6 @@
     /*
      * Various metrics on the circumstances in which tail duplication was/wasn't performed.
      */
-    private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors");
     private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd");
     private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed");
     private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther");
@@ -128,21 +127,13 @@
         }
     };
 
-    private int tailDuplicationCount;
-
-    public int getTailDuplicationCount() {
-        return tailDuplicationCount;
-    }
-
     @Override
     protected void run(StructuredGraph graph) {
         // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
             if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
-                if (tailDuplicate(merge, DEFAULT_DECISION, null)) {
-                    tailDuplicationCount++;
-                }
+                tailDuplicate(merge, DEFAULT_DECISION, null);
             }
         }
     }
@@ -168,20 +159,11 @@
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
         int fixedCount = 0;
-        boolean containsMonitor = false;
         while (fixed instanceof FixedWithNextNode) {
-            if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) {
-                containsMonitor = true;
-            }
             fixed = ((FixedWithNextNode) fixed).next();
             fixedCount++;
         }
-        if (containsMonitor) {
-            // cannot currently be handled
-            // TODO (ls) re-evaluate this limitation after changes to the lock representation and
-            // the LIR generator
-            metricDuplicationMonitors.increment();
-        } else if (fixedCount > 1) {
+        if (fixedCount > 1) {
             if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) {
                 metricDuplicationEnd.increment();
                 if (decision.doTransform(merge, fixedCount)) {
@@ -261,7 +243,6 @@
             final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
             mergeAfter.clearEnds();
             expandDuplicated(duplicatedNodes, mergeAfter);
-            retargetDependencies(duplicatedNodes, anchor);
 
             List<EndNode> endSnapshot = merge.forwardEnds().snapshot();
             List<PhiNode> phiSnapshot = merge.phis().snapshot();
@@ -536,29 +517,6 @@
         }
 
         /**
-         * Moves all depdendencies that point outside the duplicated area to the supplied value
-         * anchor node.
-         * 
-         * @param duplicatedNodes The set of duplicated nodes.
-         * @param anchor The node that will be the new target for all dependencies that point
-         *            outside the duplicated set of nodes.
-         */
-        private static void retargetDependencies(HashSet<Node> duplicatedNodes, ValueAnchorNode anchor) {
-            for (Node node : duplicatedNodes) {
-                if (node instanceof ValueNode) {
-                    NodeInputList<ValueNode> dependencies = ((ValueNode) node).dependencies();
-                    for (int i = 0; i < dependencies.size(); i++) {
-                        Node dependency = dependencies.get(i);
-                        if (dependency != null && !duplicatedNodes.contains(dependency)) {
-                            Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node);
-                            dependencies.set(i, anchor);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
          * Checks if the given node has usages that are not within the given set of nodes.
          * 
          * @param node The node whose usages are checked.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Base class for all compiler phases. Subclasses should be stateless. There will be one global
+ * instance for each compiler phase that is shared for all compilations. VM-, target- and
+ * compilation-specific data can be passed with a context object.
+ */
+public abstract class BasePhase<C> {
+
+    private String name;
+    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
+    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
+
+    protected BasePhase() {
+        this.name = this.getClass().getSimpleName();
+        if (name.endsWith("Phase")) {
+            name = name.substring(0, name.length() - "Phase".length());
+        }
+    }
+
+    protected BasePhase(String name) {
+        this.name = name;
+    }
+
+    protected String getDetailedName() {
+        return getName();
+    }
+
+    public final void apply(final StructuredGraph graph, final C context) {
+        apply(graph, context, true);
+    }
+
+    public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
+        Debug.scope(name, this, new Runnable() {
+
+            public void run() {
+                BasePhase.this.run(graph, context);
+                metricPhaseRuns.increment();
+                if (dumpGraph) {
+                    Debug.dump(graph, "After phase %s", name);
+                }
+                assert graph.verify();
+            }
+        });
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    protected abstract void run(StructuredGraph graph, C context);
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -88,6 +88,9 @@
     public static int     SlowQueueCutoff                    = 100000;
     public static boolean SlowCompileThreads                 = ____;
     public static boolean DynamicCompilePriority             = ____;
+    public static String  CompileTheWorld                    = null;
+    public static int     CompileTheWorldStartAt             = 1;
+    public static int     CompileTheWorldStopAt              = Integer.MAX_VALUE;
 
     // graph caching
     public static boolean CacheGraphs                        = true;
@@ -116,6 +119,7 @@
     // Debug settings:
     public static boolean Debug                              = true;
     public static boolean DebugReplacements                  = ____;
+    public static boolean BootstrapReplacements              = ____;
     public static boolean PerThreadDebugValues               = ____;
     public static boolean SummarizeDebugValues               = ____;
     public static boolean SummarizePerPhase                  = ____;
@@ -127,7 +131,7 @@
     public static String  MethodFilter                       = null;
     public static boolean DumpOnError                        = ____;
     public static boolean GenericDynamicCounters             = ____;
-    public static boolean BenchmarkDynamicCounters           = ____;
+    public static String  BenchmarkDynamicCounters           = null;
 
     // Ideal graph visualizer output settings
     public static boolean PrintBinaryGraphs                  = true;
@@ -151,6 +155,10 @@
     public static boolean ExitVMOnBailout                    = ____;
     public static boolean ExitVMOnException                  = true;
 
+    // HotSpot command line options
+    public static boolean HotSpotPrintCompilation            = ____;
+    public static boolean HotSpotPrintInlining               = ____;
+
     // Register allocator debugging
     public static String  RegisterPressure                   = null;
 
@@ -203,6 +211,8 @@
     public static boolean OptEliminatePartiallyRedundantGuards = true;
     public static boolean OptFilterProfiledTypes             = true;
     public static boolean OptDevirtualizeInvokesOptimistically = true;
+    public static boolean OptPushThroughPi                   = true;
+
 
     // Intrinsification settings
     public static boolean IntrinsifyObjectClone              = ____;
@@ -215,6 +225,7 @@
     public static boolean IntrinsifyMathMethods              = true;
     public static boolean IntrinsifyAESMethods               = true;
     public static boolean IntrinsifyInstalledCodeMethods     = true;
+    public static boolean IntrinsifyCallSiteTarget           = true;
     /**
      * Counts the various paths taken through snippets.
      */
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -22,28 +22,18 @@
  */
 package com.oracle.graal.phases;
 
-import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 
-public abstract class Phase {
-
-    private String name;
-    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
-    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
+/**
+ * Base class for compiler phases that don't need a context object.
+ */
+public abstract class Phase extends BasePhase<Object> {
 
     protected Phase() {
-        this.name = this.getClass().getSimpleName();
-        if (name.endsWith("Phase")) {
-            name = name.substring(0, name.length() - "Phase".length());
-        }
     }
 
     protected Phase(String name) {
-        this.name = name;
-    }
-
-    protected String getDetailedName() {
-        return getName();
+        super(name);
     }
 
     public final void apply(final StructuredGraph graph) {
@@ -51,22 +41,13 @@
     }
 
     public final void apply(final StructuredGraph graph, final boolean dumpGraph) {
-        Debug.scope(name, this, new Runnable() {
-
-            public void run() {
-                Phase.this.run(graph);
-                metricPhaseRuns.increment();
-                if (dumpGraph) {
-                    Debug.dump(graph, "After phase %s", name);
-                }
-                assert graph.verify();
-            }
-        });
-    }
-
-    public final String getName() {
-        return name;
+        apply(graph, null, dumpGraph);
     }
 
     protected abstract void run(StructuredGraph graph);
+
+    @Override
+    protected final void run(StructuredGraph graph, Object context) {
+        run(graph);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.phases;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public class PhaseSuite<C> extends BasePhase<C> {
+
+    private final List<BasePhase<? super C>> phases;
+
+    public PhaseSuite(String name, List<BasePhase<? super C>> phases) {
+        super(name);
+        this.phases = phases;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph, C context) {
+        for (BasePhase<? super C> phase : phases) {
+            phase.apply(graph, context);
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -217,7 +217,7 @@
     }
 
     protected void invoke(Invoke invoke) {
-        node(invoke.node());
+        node(invoke.asNode());
     }
 
     protected void finished() {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -39,7 +39,7 @@
 
         protected abstract void processBlock(Block block, StateT currentState);
 
-        protected abstract StateT merge(MergeNode merge, List<StateT> states);
+        protected abstract StateT merge(Block merge, List<StateT> states);
 
         protected abstract StateT cloneState(StateT oldState);
 
@@ -161,12 +161,11 @@
                     assert current.getPredecessors().size() > 1;
                     MergeNode merge = (MergeNode) current.getBeginNode();
                     ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
-                    for (int i = 0; i < merge.forwardEndCount(); i++) {
-                        StateT other = states.get(merge.forwardEndAt(i));
-                        assert other != null;
-                        mergedStates.add(other);
+                    for (Block predecessor : current.getPredecessors()) {
+                        EndNode end = (EndNode) predecessor.getEndNode();
+                        mergedStates.add(states.get(end));
                     }
-                    state = closure.merge(merge, mergedStates);
+                    state = closure.merge(current, mergedStates);
                 }
                 assert state != null;
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -39,6 +39,30 @@
 
 public final class SchedulePhase extends Phase {
 
+    /**
+     * Error thrown when a graph cannot be scheduled.
+     */
+    public static class SchedulingError extends Error {
+
+        private static final long serialVersionUID = 1621001069476473145L;
+
+        public SchedulingError() {
+            super();
+        }
+
+        /**
+         * This constructor creates a {@link SchedulingError} with a message assembled via
+         * {@link String#format(String, Object...)}.
+         * 
+         * @param format a {@linkplain Formatter format} string
+         * @param args parameters to {@link String#format(String, Object...)}
+         */
+        public SchedulingError(String format, Object... args) {
+            super(String.format(format, args));
+        }
+
+    }
+
     public static enum SchedulingStrategy {
         EARLIEST, LATEST, LATEST_OUT_OF_LOOPS
     }
@@ -91,7 +115,7 @@
         }
 
         @Override
-        protected HashSet<FloatingReadNode> merge(MergeNode merge, List<HashSet<FloatingReadNode>> states) {
+        protected HashSet<FloatingReadNode> merge(Block 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));
@@ -169,8 +193,8 @@
 
     /**
      * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the
-     * scheduling built by @link {@link #run(StructuredGraph)}. This method should thus only be
-     * called when run has been successfully executed.
+     * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called
+     * when run has been successfully executed.
      */
     public void scheduleGraph() {
         assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
@@ -207,7 +231,9 @@
     private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) {
         for (Block block : cfg.getBlocks()) {
             List<ScheduledNode> nodes = new ArrayList<>();
-            assert blockToNodesMap.get(block) == null;
+            if (blockToNodesMap.get(block) != null) {
+                throw new SchedulingError();
+            }
             blockToNodesMap.put(block, nodes);
             for (FixedNode node : block.getNodes()) {
                 nodes.add(node);
@@ -234,8 +260,9 @@
         }
         // PhiNodes and FixedNodes should already have been placed in blocks by
         // ControlFlowGraph.identifyBlocks
-        assert !(node instanceof PhiNode) : node;
-        assert !(node instanceof FixedNode) : node;
+        if (node instanceof PhiNode || node instanceof FixedNode) {
+            throw new SchedulingError("%s should already have been placed in a block", node);
+        }
 
         Block block;
         switch (strategy) {
@@ -251,8 +278,10 @@
                     // 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 + ")";
+                    if (!earliestBlock.dominates(block)) {
+                        throw new SchedulingError("%s: Graph cannot be scheduled : inconsistent for %s, %d usages, (%s needs to dominate %s)", node.graph(), node, node.usages().count(),
+                                        earliestBlock, block);
+                    }
                 }
                 break;
             default:
@@ -271,7 +300,9 @@
     private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) {
         CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
         for (Node succ : node.successors().nonNull()) {
-            assert cfg.getNodeToBlock().get(succ) != null;
+            if (cfg.getNodeToBlock().get(succ) == null) {
+                throw new SchedulingError();
+            }
             cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
         ensureScheduledUsages(node, strategy);
@@ -281,7 +312,9 @@
         List<FixedNode> usages = phantomUsages.get(node);
         if (usages != null) {
             for (FixedNode usage : usages) {
-                assert cfg.getNodeToBlock().get(usage) != null;
+                if (cfg.getNodeToBlock().get(usage) == null) {
+                    throw new SchedulingError();
+                }
                 cdbc.apply(cfg.getNodeToBlock().get(usage));
             }
         }
@@ -331,7 +364,9 @@
          */
         BitSet dominators = new BitSet(cfg.getBlocks().length);
 
-        assert node.predecessor() == null;
+        if (node.predecessor() != null) {
+            throw new SchedulingError();
+        }
         for (Node input : node.inputs().nonNull()) {
             assert input instanceof ValueNode;
             Block inputEarliest;
@@ -356,7 +391,9 @@
     }
 
     private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
-        assert latestBlock != null : "no latest : " + n;
+        if (latestBlock == null) {
+            throw new SchedulingError("no latest : %s", n);
+        }
         Block cur = latestBlock;
         Block result = latestBlock;
         while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) {
@@ -378,7 +415,9 @@
      * @param closure the closure that will be called for each block
      */
     private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) {
-        assert !(node instanceof PhiNode);
+        if (node instanceof PhiNode) {
+            throw new SchedulingError(node.toString());
+        }
 
         if (usage instanceof PhiNode) {
             // An input to a PhiNode is used at the end of the predecessor block that corresponds to
@@ -388,7 +427,9 @@
             PhiNode phi = (PhiNode) usage;
             MergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
-            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
+            if (mergeBlock == null) {
+                throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id));
+            }
             for (int i = 0; i < phi.valueCount(); ++i) {
                 if (phi.valueAt(i) == node) {
                     if (mergeBlock.getPredecessorCount() <= i) {
@@ -412,7 +453,9 @@
                     blocksForUsage(node, unscheduledUsage, closure, strategy);
                 } else if (unscheduledUsage instanceof MergeNode) {
                     // Only FrameStates can be connected to MergeNodes.
-                    assert usage instanceof FrameState;
+                    if (!(usage instanceof FrameState)) {
+                        throw new SchedulingError(usage.toString());
+                    }
                     // If a FrameState belongs to a MergeNode then it's inputs will be placed at the
                     // common dominator of all EndNodes.
                     for (Node pred : unscheduledUsage.cfgPredecessors()) {
@@ -420,8 +463,12 @@
                     }
                 } else {
                     // For the time being, only FrameStates can be connected to StateSplits.
-                    assert usage instanceof FrameState;
-                    assert unscheduledUsage instanceof StateSplit;
+                    if (!(usage instanceof FrameState)) {
+                        throw new SchedulingError(usage.toString());
+                    }
+                    if (!(unscheduledUsage instanceof StateSplit || unscheduledUsage instanceof DeoptimizingNode)) {
+                        throw new SchedulingError(unscheduledUsage.toString());
+                    }
                     // Otherwise: Put the input into the same block as the usage.
                     assignBlockToNode((ScheduledNode) unscheduledUsage, strategy);
                     closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
@@ -459,8 +506,12 @@
     }
 
     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;
+        if (visited.isMarked(b.getBeginNode()) || cfg.blockFor(b.getBeginNode()) != b) {
+            throw new SchedulingError();
+        }
+        if (visited.isMarked(b.getEndNode()) || cfg.blockFor(b.getEndNode()) != b) {
+            throw new SchedulingError();
+        }
 
         List<ScheduledNode> sortedInstructions;
         switch (strategy) {
@@ -520,7 +571,9 @@
     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);
+            if (visited.isMarked(state)) {
+                throw new SchedulingError();
+            }
 
             for (Node input : state.inputs()) {
                 if (input instanceof VirtualState) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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.phases.tiers;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class HighTierContext extends PhaseContext {
+
+    public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions) {
+        super(runtime, assumptions);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+package com.oracle.graal.phases.tiers;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class PhaseContext {
+
+    private final MetaAccessProvider runtime;
+    private final Assumptions assumptions;
+
+    public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions) {
+        this.runtime = runtime;
+        this.assumptions = assumptions;
+    }
+
+    public MetaAccessProvider getRuntime() {
+        return runtime;
+    }
+
+    public Assumptions getAssumptions() {
+        return assumptions;
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Mon Apr 15 08:51:19 2013 +0200
@@ -288,7 +288,9 @@
         }
 
         void warning(int offset, String message) {
+            // CheckStyle: stop system..print check
             System.err.println("Warning: " + errorMessage(offset, message));
+            // CheckStyle: resume system..print check
         }
 
         String errorMessage(int offset, String message) {
@@ -316,8 +318,10 @@
             int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1;
 
             String l = input.substring(lineStart, lineStart + 10);
+            // CheckStyle: stop system..print check
             System.out.println("YYY" + input.substring(index, index + 10) + "...");
             System.out.println("XXX" + l + "...");
+            // CheckStyle: resume system..print check
 
             int pos = input.indexOf(HexCodeFile.NEW_LINE, 0);
             int line = 1;
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,18 +23,20 @@
 package com.oracle.graal.replacements.amd64;
 
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 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.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 
 /**
  * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
@@ -54,7 +56,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
+    public static int f2i(float input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -80,7 +82,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
+    public static long f2l(float input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -106,7 +108,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
+    public static int d2i(double input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -132,7 +134,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
+    public static long d2l(double input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -146,34 +148,26 @@
         return result;
     }
 
-    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod f2i;
-        private final ResolvedJavaMethod f2l;
-        private final ResolvedJavaMethod d2i;
-        private final ResolvedJavaMethod d2l;
+        private final EnumMap<Op, SnippetInfo> snippets;
 
-        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 Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+
+            snippets = new EnumMap<>(Op.class);
+            snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i"));
+            snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l"));
+            snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i"));
+            snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l"));
         }
 
         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);
+            SnippetInfo key = snippets.get(convert.opcode);
+            if (key == null) {
+                return;
             }
-        }
 
-        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
@@ -183,11 +177,13 @@
 
             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);
+            Arguments args = new Arguments(key);
+            args.add("input", convert.value());
+            args.add("result", convert);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args);
+            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args);
         }
     }
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CheckCastTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +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.replacements;
-
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests the implementation of checkcast, allowing profiling information to be manually specified.
- */
-public class CheckCastTest extends TypeCheckTest {
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
-        if (ccn != null) {
-            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile));
-            graph.replaceFixedWithFixed(ccn, ccnNew);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("asNumber", profile(), 111);
-        test("asNumber", profile(Integer.class), 111);
-        test("asNumber", profile(Long.class, Short.class), 111);
-        test("asNumberExt", profile(), 111);
-        test("asNumberExt", profile(Integer.class), 111);
-        test("asNumberExt", profile(Long.class, Short.class), 111);
-    }
-
-    @LongTest
-    public void test2() {
-        test("asString", profile(), "111");
-        test("asString", profile(String.class), "111");
-        test("asString", profile(String.class), "111");
-
-        final String nullString = null;
-        test("asString", profile(), nullString);
-        test("asString", profile(String.class), nullString);
-        test("asString", profile(String.class), nullString);
-
-        test("asStringExt", profile(), "111");
-        test("asStringExt", profile(String.class), "111");
-        test("asStringExt", profile(String.class), "111");
-    }
-
-    @LongTest
-    public void test3() {
-        test("asNumber", profile(), "111");
-    }
-
-    @LongTest
-    public void test4() {
-        test("asString", profile(String.class), 111);
-    }
-
-    @LongTest
-    public void test5() {
-        test("asNumberExt", profile(), "111");
-    }
-
-    @LongTest
-    public void test6() {
-        test("asStringExt", profile(String.class), 111);
-    }
-
-    @LongTest
-    public void test7() {
-        Throwable throwable = new Exception();
-        test("asThrowable", profile(), throwable);
-        test("asThrowable", profile(Throwable.class), throwable);
-        test("asThrowable", profile(Exception.class, Error.class), throwable);
-    }
-
-    @LongTest
-    public void test8() {
-        test("arrayStore", new Object[100], "111");
-    }
-
-    @LongTest
-    public void test8_1() {
-        test("arrayFill", new Object[100], "111");
-    }
-
-    public static Number asNumber(Object o) {
-        return (Number) o;
-    }
-
-    public static String asString(Object o) {
-        return (String) o;
-    }
-
-    public static Throwable asThrowable(Object o) {
-        return (Throwable) o;
-    }
-
-    public static ValueNode asValueNode(Object o) {
-        return (ValueNode) o;
-    }
-
-    public static Number asNumberExt(Object o) {
-        Number n = (Number) o;
-        return n.intValue() + 10;
-    }
-
-    public static String asStringExt(Object o) {
-        String s = (String) o;
-        return "#" + s;
-    }
-
-    public static Object[] arrayStore(Object[] arr, Object value) {
-        arr[15] = value;
-        return arr;
-    }
-
-    public static Object[] arrayFill(Object[] arr, Object value) {
-        for (int i = 0; i < arr.length; i++) {
-            arr[i] = value;
-        }
-        return arr;
-    }
-
-    static class Depth1 implements Cloneable {
-    }
-
-    static class Depth2 extends Depth1 {
-    }
-
-    static class Depth3 extends Depth2 {
-    }
-
-    static class Depth4 extends Depth3 {
-    }
-
-    static class Depth5 extends Depth4 {
-    }
-
-    static class Depth6 extends Depth5 {
-    }
-
-    static class Depth7 extends Depth6 {
-    }
-
-    static class Depth8 extends Depth7 {
-    }
-
-    static class Depth9 extends Depth8 {
-    }
-
-    static class Depth10 extends Depth9 {
-    }
-
-    static class Depth11 extends Depth10 {
-    }
-
-    static class Depth12 extends Depth11 {
-    }
-
-    static class Depth13 extends Depth12 {
-    }
-
-    static class Depth14 extends Depth12 {
-    }
-
-    public static Depth12 asDepth12(Object o) {
-        return (Depth12) o;
-    }
-
-    public static Depth12[][] asDepth12Arr(Object o) {
-        return (Depth12[][]) o;
-    }
-
-    public static Cloneable asCloneable(Object o) {
-        return (Cloneable) o;
-    }
-
-    @LongTest
-    public void test9() {
-        Object o = new Depth13();
-        test("asDepth12", profile(), o);
-        test("asDepth12", profile(Depth13.class), o);
-        test("asDepth12", profile(Depth13.class, Depth14.class), o);
-    }
-
-    @LongTest
-    public void test10() {
-        Object o = new Depth13[3][];
-        test("asDepth12Arr", o);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfDynamicTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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.replacements;
-
-import com.oracle.graal.test.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests for {@link InstanceOfDynamicNode}.
- */
-public class InstanceOfDynamicTest extends GraalCompilerTest {
-
-    public static int id(int value) {
-        return value;
-    }
-
-    @LongTest
-    public void test100() {
-        final Object nul = null;
-        test("isStringDynamic", nul);
-        test("isStringDynamic", "object");
-        test("isStringDynamic", Object.class);
-    }
-
-    @LongTest
-    public void test101() {
-        final Object nul = null;
-        test("isStringIntDynamic", nul);
-        test("isStringIntDynamic", "object");
-        test("isStringIntDynamic", Object.class);
-    }
-
-    @LongTest
-    public void test103() {
-        test("isInstanceDynamic", String.class, null);
-        test("isInstanceDynamic", String.class, "object");
-        test("isInstanceDynamic", String.class, Object.class);
-        test("isInstanceDynamic", int.class, null);
-        test("isInstanceDynamic", int.class, "Object");
-        test("isInstanceDynamic", int.class, Object.class);
-    }
-
-    @LongTest
-    public void test104() {
-        test("isInstanceIntDynamic", String.class, null);
-        test("isInstanceIntDynamic", String.class, "object");
-        test("isInstanceIntDynamic", String.class, Object.class);
-        test("isInstanceIntDynamic", int.class, null);
-        test("isInstanceIntDynamic", int.class, "Object");
-        test("isInstanceIntDynamic", int.class, Object.class);
-    }
-
-    public static boolean isStringDynamic(Object o) {
-        return String.class.isInstance(o);
-    }
-
-    public static int isStringIntDynamic(Object o) {
-        if (String.class.isInstance(o)) {
-            return o.toString().length();
-        }
-        return o.getClass().getName().length();
-    }
-
-    public static boolean isInstanceDynamic(Class c, Object o) {
-        return c.isInstance(o);
-    }
-
-    public static int isInstanceIntDynamic(Class c, Object o) {
-        if (c.isInstance(o)) {
-            return o.toString().length();
-        }
-        return o.getClass().getName().length();
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +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.replacements;
-
-import java.util.*;
-
-
-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.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.replacements.CheckCastTest.*;
-
-/**
- * Tests the implementation of instanceof, allowing profiling information to be manually specified.
- */
-public class InstanceOfTest extends TypeCheckTest {
-
-    @Override
-    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
-        phasePlan.disablePhase(InliningPhase.class);
-    }
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
-        if (ion != null) {
-            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile));
-            graph.replaceFloating(ion, ionNew);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("isString", profile(), "object");
-        test("isString", profile(String.class), "object");
-
-        test("isString", profile(), Object.class);
-        test("isString", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test2() {
-        test("isStringInt", profile(), "object");
-        test("isStringInt", profile(String.class), "object");
-
-        test("isStringInt", profile(), Object.class);
-        test("isStringInt", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test2_1() {
-        test("isStringIntComplex", profile(), "object");
-        test("isStringIntComplex", profile(String.class), "object");
-
-        test("isStringIntComplex", profile(), Object.class);
-        test("isStringIntComplex", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test3() {
-        Throwable throwable = new Exception();
-        test("isThrowable", profile(), throwable);
-        test("isThrowable", profile(Throwable.class), throwable);
-        test("isThrowable", profile(Exception.class, Error.class), throwable);
-
-        test("isThrowable", profile(), Object.class);
-        test("isThrowable", profile(Throwable.class), Object.class);
-        test("isThrowable", profile(Exception.class, Error.class), Object.class);
-    }
-
-    @LongTest
-    public void test3_1() {
-        onlyFirstIsException(new Exception(), new Error());
-        test("onlyFirstIsException", profile(), new Exception(), new Error());
-        test("onlyFirstIsException", profile(), new Error(), new Exception());
-        test("onlyFirstIsException", profile(), new Exception(), new Exception());
-        test("onlyFirstIsException", profile(), new Error(), new Error());
-    }
-
-    @LongTest
-    public void test4() {
-        Throwable throwable = new Exception();
-        test("isThrowableInt", profile(), throwable);
-        test("isThrowableInt", profile(Throwable.class), throwable);
-        test("isThrowableInt", profile(Exception.class, Error.class), throwable);
-
-        test("isThrowableInt", profile(), Object.class);
-        test("isThrowableInt", profile(Throwable.class), Object.class);
-        test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
-    }
-
-    @LongTest
-    public void test5() {
-        Map map = new HashMap<>();
-        test("isMap", profile(), map);
-        test("isMap", profile(HashMap.class), map);
-        test("isMap", profile(TreeMap.class, HashMap.class), map);
-
-        test("isMap", profile(), Object.class);
-        test("isMap", profile(HashMap.class), Object.class);
-        test("isMap", profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    @LongTest
-    public void test6() {
-        Map map = new HashMap<>();
-        test("isMapInt", profile(), map);
-        test("isMapInt", profile(HashMap.class), map);
-        test("isMapInt", profile(TreeMap.class, HashMap.class), map);
-
-        test("isMapInt", profile(), Object.class);
-        test("isMapInt", profile(HashMap.class), Object.class);
-        test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    @LongTest
-    public void test7() {
-        Object o = new Depth13();
-        test("isDepth12", profile(), o);
-        test("isDepth12", profile(Depth13.class), o);
-        test("isDepth12", profile(Depth13.class, Depth14.class), o);
-
-        o = "not a depth";
-        test("isDepth12", profile(), o);
-        test("isDepth12", profile(Depth13.class), o);
-        test("isDepth12", profile(Depth13.class, Depth14.class), o);
-    }
-
-    @LongTest
-    public void test8() {
-        Object o = new Depth13();
-        test("isDepth12Int", profile(), o);
-        test("isDepth12Int", profile(Depth13.class), o);
-        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
-
-        o = "not a depth";
-        test("isDepth12Int", profile(), o);
-        test("isDepth12Int", profile(Depth13.class), o);
-        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
-    }
-
-    public static boolean isString(Object o) {
-        return o instanceof String;
-    }
-
-    public static int isStringInt(Object o) {
-        if (o instanceof String) {
-            return id(1);
-        }
-        return id(0);
-    }
-
-    public static int isStringIntComplex(Object o) {
-        if (o instanceof String || o instanceof Integer) {
-            return id(o instanceof String ? 1 : 0);
-        }
-        return id(0);
-    }
-
-    public static int id(int value) {
-        return value;
-    }
-
-    public static boolean isThrowable(Object o) {
-        return ((Throwable) o) instanceof Exception;
-    }
-
-    public static int onlyFirstIsException(Throwable t1, Throwable t2) {
-        if (t1 instanceof Exception ^ t2 instanceof Exception) {
-            return t1 instanceof Exception ? 1 : -1;
-        }
-        return -1;
-    }
-
-    public static int isThrowableInt(Object o) {
-        int result = o instanceof Throwable ? 4 : 5;
-        if (o instanceof Throwable) {
-            return id(4);
-        }
-        return result;
-    }
-
-    public static boolean isMap(Object o) {
-        return o instanceof Map;
-    }
-
-    public static int isMapInt(Object o) {
-        if (o instanceof Map) {
-            return id(1);
-        }
-        return id(0);
-    }
-
-    public static boolean isDepth12(Object o) {
-        return o instanceof Depth12;
-    }
-
-    public static int isDepth12Int(Object o) {
-        if (o instanceof Depth12) {
-            return id(0);
-        }
-        return id(0);
-    }
-
-    abstract static class MySite {
-
-        final int offset;
-
-        MySite(int offset) {
-            this.offset = offset;
-        }
-    }
-
-    static class MyMark extends MySite {
-
-        MyMark(int offset) {
-            super(offset);
-        }
-    }
-
-    abstract static class MySafepoint extends MySite {
-
-        MySafepoint(int offset) {
-            super(offset);
-        }
-    }
-
-    static class MyCall extends MySafepoint {
-
-        MyCall(int offset) {
-            super(offset);
-        }
-    }
-
-    @LongTest
-    public void test9() {
-        MyCall callAt63 = new MyCall(63);
-        MyMark markAt63 = new MyMark(63);
-        test("compareMySites", callAt63, callAt63);
-        test("compareMySites", callAt63, markAt63);
-        test("compareMySites", markAt63, callAt63);
-        test("compareMySites", markAt63, markAt63);
-    }
-
-    public static int compareMySites(MySite s1, MySite s2) {
-        if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) {
-            return s1 instanceof MyMark ? -1 : 1;
-        }
-        return s1.offset - s2.offset;
-    }
-
-    @LongTest
-    public void test10() {
-        Mark[] noMarks = {};
-        Call callAt63 = new Call(null, 63, 5, true, null);
-        Mark markAt63 = new Mark(63, "1", noMarks);
-        test("compareSites", callAt63, callAt63);
-        test("compareSites", callAt63, markAt63);
-        test("compareSites", markAt63, callAt63);
-        test("compareSites", markAt63, markAt63);
-    }
-
-    public static int compareSites(Site s1, Site s2) {
-        if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
-            return s1 instanceof Mark ? -1 : 1;
-        }
-        return s1.pcOffset - s2.pcOffset;
-    }
-
-    /**
-     * This test exists to show the kind of pattern that is be optimizable by
-     * {@code removeIntermediateMaterialization()} in {@link IfNode}.
-     * <p>
-     * 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}.
-     */
-    @LongTest
-    public void test_removeIntermediateMaterialization() {
-        List<String> list = Arrays.asList("1", "2", "3", "4");
-        test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
-        test("removeIntermediateMaterialization", profile(), list, null, "yes", "no");
-        test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no");
-    }
-
-    public static String removeIntermediateMaterialization(List<Object> list, Object e, String a, String b) {
-        boolean test;
-        if (list == null || e == null) {
-            test = false;
-        } else {
-            test = false;
-            for (Object i : list) {
-                if (i.equals(e)) {
-                    test = true;
-                    break;
-                }
-            }
-        }
-        if (test) {
-            return a;
-        }
-        return b;
-    }
-
-    abstract static class A {
-    }
-
-    static class B extends A {
-    }
-
-    static class C extends B {
-    }
-
-    abstract static class D extends C {
-    }
-
-    public static boolean isArrayOfA(Object o) {
-        return o instanceof A[];
-    }
-
-    public static boolean isArrayOfB(Object o) {
-        return o instanceof B[];
-    }
-
-    public static boolean isArrayOfC(Object o) {
-        return o instanceof C[];
-    }
-
-    public static boolean isArrayOfD(Object o) {
-        return o instanceof D[];
-    }
-
-    @LongTest
-    public void testArray() {
-        Object aArray = new A[10];
-        test("isArrayOfA", aArray);
-
-        Object bArray = new B[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-
-        Object cArray = new C[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfA", cArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-        test("isArrayOfB", cArray);
-        test("isArrayOfC", aArray);
-        test("isArrayOfC", bArray);
-        test("isArrayOfC", cArray);
-
-        Object dArray = new D[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfA", cArray);
-        test("isArrayOfA", dArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-        test("isArrayOfB", cArray);
-        test("isArrayOfB", dArray);
-        test("isArrayOfC", aArray);
-        test("isArrayOfC", bArray);
-        test("isArrayOfC", cArray);
-        test("isArrayOfC", dArray);
-        test("isArrayOfD", aArray);
-        test("isArrayOfD", bArray);
-        test("isArrayOfD", cArray);
-        test("isArrayOfD", dArray);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InvokeTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +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.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * Tests the implementation of the snippets for lowering the INVOKE* instructions.
- */
-public class InvokeTest extends GraalCompilerTest {
-
-    @Override
-    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
-        phasePlan.disablePhase(InliningPhase.class);
-    }
-
-    public interface I {
-
-        String virtualMethod(String s);
-    }
-
-    public static class A implements I {
-
-        final String name = "A";
-
-        public String virtualMethod(String s) {
-            return name + s;
-        }
-    }
-
-    @SuppressWarnings("static-method")
-    private String privateMethod(String s) {
-        return s;
-    }
-
-    @Test
-    public void test1() {
-        test("invokestatic", "a string");
-        test("invokespecialConstructor", "a string");
-        test("invokespecial", this, "a string");
-        test("invokevirtual", new A(), "a string");
-        test("invokevirtual2", new A(), "a string");
-        test("invokeinterface", new A(), "a string");
-        Object[] args = {null};
-        test("invokestatic", args);
-        test("invokespecialConstructor", args);
-        test("invokespecial", null, null);
-        test("invokevirtual", null, null);
-        test("invokevirtual2", null, null);
-        test("invokeinterface", null, null);
-    }
-
-    public static String invokestatic(String s) {
-        return staticMethod(s);
-    }
-
-    public static String staticMethod(String s) {
-        return s;
-    }
-
-    public static String invokespecialConstructor(String s) {
-        return new A().virtualMethod(s);
-    }
-
-    public static String invokespecial(InvokeTest a, String s) {
-        return a.privateMethod(s);
-    }
-
-    public static String invokevirtual(A a, String s) {
-        return a.virtualMethod(s);
-    }
-
-    public static String invokevirtual2(A a, String s) {
-        a.virtualMethod(s);
-        return a.virtualMethod(s);
-    }
-
-    public static String invokeinterface(I i, String s) {
-        return i.virtualMethod(s);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MethodSubstitutionTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +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.replacements;
-
-import static org.junit.Assert.*;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that
- * there are no remaining invocations in the graph. This is sufficient if the method that is being
- * substituted is a native method. For Java methods, additional checks are necessary.
- */
-public abstract class MethodSubstitutionTest extends GraalCompilerTest {
-
-    protected StructuredGraph test(final String snippet) {
-        return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable<StructuredGraph>() {
-
-            @Override
-            public StructuredGraph call() {
-                StructuredGraph graph = parse(snippet);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                Assumptions assumptions = new Assumptions(true);
-                new ComputeProbabilityPhase().apply(graph);
-                Debug.dump(graph, "Graph");
-                new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new DeadCodeEliminationPhase().apply(graph);
-
-                assertNotInGraph(graph, Invoke.class);
-                return graph;
-            }
-        });
-    }
-
-    protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
-        for (Node node : graph.getNodes()) {
-            if (clazz.isInstance(node)) {
-                fail(node.toString());
-            }
-        }
-        return graph;
-    }
-
-    protected static StructuredGraph assertInGraph(StructuredGraph graph, Class<?> clazz) {
-        for (Node node : graph.getNodes()) {
-            if (clazz.isInstance(node)) {
-                return graph;
-            }
-        }
-        fail("Graph does not contain a node of class " + clazz.getName());
-        return graph;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MonitorTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +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.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.virtual.phases.ea.*;
-
-public class MonitorTest extends GraalCompilerTest {
-
-    @Test
-    public void test0() {
-        test("lockObjectSimple", new Object(), new Object());
-        test("lockObjectSimple", new Object(), null);
-    }
-
-    @Test
-    public void test0_1() {
-        test("lockThisSimple", "test1", new Object());
-        test("lockThisSimple", "test1", null);
-    }
-
-    @Test
-    public void test0_2() {
-        test("lockObjectSimple", null, "test1");
-    }
-
-    @Test
-    public void test1_1() {
-        test("lockObject", new Object(), "test1", new String[1]);
-    }
-
-    @Test
-    public void test1_2() {
-        test("lockObject", null, "test1_1", new String[1]);
-    }
-
-    @Test
-    public void test2() {
-        test("lockThis", "test2", new String[1]);
-    }
-
-    /**
-     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
-     */
-    @Test
-    public void test3() {
-        test("lockLocalObject", "test3", new String[1]);
-    }
-
-    /**
-     * Tests recursive locking of objects which should be biasable.
-     */
-    @Test
-    public void test4() {
-        Chars src = new Chars("1234567890".toCharArray());
-        Chars dst = new Chars(src.data.length);
-        test("copyObj", src, dst, 100);
-    }
-
-    /**
-     * Tests recursive locking of objects which do not appear to be biasable.
-     */
-    @Test
-    public void test5() {
-        char[] src = "1234567890".toCharArray();
-        char[] dst = new char[src.length];
-        test("copyArr", src, dst, 100);
-    }
-
-    /**
-     * Extends {@link #test4()} with contention.
-     */
-    @Test
-    public void test6() {
-        Chars src = new Chars("1234567890".toCharArray());
-        Chars dst = new Chars(src.data.length);
-        int n = Runtime.getRuntime().availableProcessors();
-        testN(n, "copyObj", src, dst, 100);
-    }
-
-    /**
-     * Extends {@link #test5()} with contention.
-     */
-    @Test
-    public void test7() {
-        char[] src = "1234567890".toCharArray();
-        char[] dst = new char[src.length];
-        int n = Runtime.getRuntime().availableProcessors();
-        testN(n, "copyArr", src, dst, 100);
-    }
-
-    private static String setAndGet(String[] box, String value) {
-        synchronized (box) {
-            box[0] = null;
-        }
-
-        // Do a GC while a object is locked (by the caller)
-        System.gc();
-
-        synchronized (box) {
-            box[0] = value;
-        }
-        return box[0];
-    }
-
-    public static Object lockObjectSimple(Object o, Object value) {
-        synchronized (o) {
-            value.hashCode();
-            return value;
-        }
-    }
-
-    public String lockThisSimple(String value, Object o) {
-        synchronized (this) {
-            synchronized (value) {
-                o.hashCode();
-                return value;
-            }
-        }
-    }
-
-    public static String lockObject(Object o, String value, String[] box) {
-        synchronized (o) {
-            return setAndGet(box, value);
-        }
-    }
-
-    public String lockThis(String value, String[] box) {
-        synchronized (this) {
-            return setAndGet(box, value);
-        }
-    }
-
-    public static String lockLocalObject(String value, String[] box) {
-        Object o = new Object();
-        synchronized (o) {
-            return setAndGet(box, value);
-        }
-    }
-
-    static class Chars {
-
-        final char[] data;
-
-        public Chars(int size) {
-            this.data = new char[size];
-        }
-
-        public Chars(char[] data) {
-            this.data = data;
-        }
-    }
-
-    public static String copyObj(Chars src, Chars dst, int n) {
-        for (int j = 0; j < n; j++) {
-            for (int i = 0; i < src.data.length; i++) {
-                synchronized (src) {
-                    synchronized (dst) {
-                        synchronized (src) {
-                            synchronized (dst) {
-                                dst.data[i] = src.data[i];
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return new String(dst.data);
-    }
-
-    public static String copyArr(char[] src, char[] dst, int n) {
-        for (int j = 0; j < n; j++) {
-            for (int i = 0; i < src.length; i++) {
-                synchronized (src) {
-                    synchronized (dst) {
-                        synchronized (src) {
-                            synchronized (dst) {
-                                dst[i] = src[i];
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return new String(dst);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewArrayTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +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.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-
-/**
- * Tests the implementation of {@code [A]NEWARRAY}.
- */
-public class NewArrayTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-        if (expected instanceof int[]) {
-            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
-        } else if (expected instanceof byte[]) {
-            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
-        } else if (expected instanceof char[]) {
-            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
-        } else if (expected instanceof short[]) {
-            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
-        } else if (expected instanceof float[]) {
-            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
-        } else if (expected instanceof long[]) {
-            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
-        } else if (expected instanceof double[]) {
-            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
-        } else if (expected instanceof Object[]) {
-            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
-        } else {
-            Assert.fail("non-array value encountered: " + expected);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
-            test("new" + type + "Array7");
-            test("new" + type + "ArrayMinus7");
-            test("new" + type + "Array", 7);
-            test("new" + type + "Array", -7);
-            test("new" + type + "Array", Integer.MAX_VALUE);
-            test("new" + type + "Array", Integer.MIN_VALUE);
-        }
-    }
-
-    public static Object newCharArray7() {
-        return new char[7];
-    }
-
-    public static Object newCharArrayMinus7() {
-        return new char[-7];
-    }
-
-    public static Object newCharArray(int length) {
-        return new char[length];
-    }
-
-    public static Object newShortArray7() {
-        return new short[7];
-    }
-
-    public static Object newShortArrayMinus7() {
-        return new short[-7];
-    }
-
-    public static Object newShortArray(int length) {
-        return new short[length];
-    }
-
-    public static Object newFloatArray7() {
-        return new float[7];
-    }
-
-    public static Object newFloatArrayMinus7() {
-        return new float[-7];
-    }
-
-    public static Object newFloatArray(int length) {
-        return new float[length];
-    }
-
-    public static Object newLongArray7() {
-        return new long[7];
-    }
-
-    public static Object newLongArrayMinus7() {
-        return new long[-7];
-    }
-
-    public static Object newLongArray(int length) {
-        return new long[length];
-    }
-
-    public static Object newDoubleArray7() {
-        return new double[7];
-    }
-
-    public static Object newDoubleArrayMinus7() {
-        return new double[-7];
-    }
-
-    public static Object newDoubleArray(int length) {
-        return new double[length];
-    }
-
-    public static Object newIntArray7() {
-        return new int[7];
-    }
-
-    public static Object newIntArrayMinus7() {
-        return new int[-7];
-    }
-
-    public static Object newIntArray(int length) {
-        return new int[length];
-    }
-
-    public static Object newByteArray7() {
-        return new byte[7];
-    }
-
-    public static Object newByteArrayMinus7() {
-        return new byte[-7];
-    }
-
-    public static Object newByteArray(int length) {
-        return new byte[length];
-    }
-
-    public static Object newStringArray7() {
-        return new String[7];
-    }
-
-    public static Object newStringArrayMinus7() {
-        return new String[-7];
-    }
-
-    public static Object newStringArray(int length) {
-        return new String[length];
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewInstanceTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +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.replacements;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-
-/**
- * Tests the implementation of {@code NEW}.
- */
-public class NewInstanceTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-
-        if (expected instanceof Object[]) {
-            Assert.assertTrue(actual instanceof Object[]);
-            Object[] eArr = (Object[]) expected;
-            Object[] aArr = (Object[]) actual;
-            Assert.assertTrue(eArr.length == aArr.length);
-            for (int i = 0; i < eArr.length; i++) {
-                assertEquals(eArr[i], aArr[i]);
-            }
-        } else if (expected.getClass() != Object.class) {
-            try {
-                expected.getClass().getDeclaredMethod("equals", Object.class);
-                super.assertEquals(expected, actual);
-            } catch (Exception e) {
-            }
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("newObject");
-    }
-
-    @LongTest
-    public void test2() {
-        test("newObjectTwice");
-    }
-
-    public static Object newObject() {
-        return new Object();
-    }
-
-    @LongTest
-    public void test3() {
-        test("newObjectLoop", 100);
-    }
-
-    @LongTest
-    public void test4() {
-        test("newBigObject");
-    }
-
-    @LongTest
-    public void test5() {
-        test("newSomeObject");
-    }
-
-    @LongTest
-    public void test6() {
-        test("newEmptyString");
-    }
-
-    @LongTest
-    public void test7() {
-        test("newString", "value");
-    }
-
-    @LongTest
-    public void test8() {
-        test("newHashMap", 31);
-    }
-
-    @LongTest
-    public void test9() {
-        test("newRegression", true);
-    }
-
-    public static Object[] newObjectTwice() {
-        Object[] res = {new Object(), new Object()};
-        return res;
-    }
-
-    public static Object[] newObjectLoop(int n) {
-        Object[] res = new Object[n];
-        for (int i = 0; i < n; i++) {
-            res[i] = new Object();
-        }
-        return res;
-    }
-
-    public static BigObject newBigObject() {
-        return new BigObject();
-    }
-
-    public static SomeObject newSomeObject() {
-        return new SomeObject();
-    }
-
-    public static String newEmptyString() {
-        return new String();
-    }
-
-    public static String newString(String value) {
-        return new String(value);
-    }
-
-    public static HashMap newHashMap(int initialCapacity) {
-        return new HashMap(initialCapacity);
-    }
-
-    static class SomeObject {
-
-        String name = "o1";
-        HashMap<String, Object> map = new HashMap<>();
-
-        public SomeObject() {
-            map.put(name, this.getClass());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof SomeObject) {
-                SomeObject so = (SomeObject) obj;
-                return so.name.equals(name) && so.map.equals(map);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-    }
-
-    static class BigObject {
-
-        Object f01;
-        Object f02;
-        Object f03;
-        Object f04;
-        Object f05;
-        Object f06;
-        Object f07;
-        Object f08;
-        Object f09;
-        Object f10;
-        Object f12;
-        Object f13;
-        Object f14;
-        Object f15;
-        Object f16;
-        Object f17;
-        Object f18;
-        Object f19;
-        Object f20;
-        Object f21;
-        Object f22;
-        Object f23;
-        Object f24;
-        Object f25;
-        Object f26;
-        Object f27;
-        Object f28;
-        Object f29;
-        Object f30;
-        Object f31;
-        Object f32;
-        Object f33;
-        Object f34;
-        Object f35;
-        Object f36;
-        Object f37;
-        Object f38;
-        Object f39;
-        Object f40;
-        Object f41;
-        Object f42;
-        Object f43;
-        Object f44;
-        Object f45;
-    }
-
-    /**
-     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
-     * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
-     * allocated B object in the true branch overwrote the allocated array. The cause is that
-     * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
-     * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
-     * first place).
-     */
-    public static Object newRegression(boolean condition) {
-        Object result;
-        if (condition) {
-            Object[] arr = {0, 1, 2, 3, 4, 5};
-            result = new B();
-            for (int i = 0; i < arr.length; ++i) {
-                // If the bug exists, the values of arr will now be deadbeef values
-                // and the virtual dispatch will cause a segfault. This can result in
-                // either a VM crash or a spurious NullPointerException.
-                if (arr[i].equals(Integer.valueOf(i))) {
-                    return false;
-                }
-            }
-        } else {
-            result = new B();
-        }
-        return result;
-    }
-
-    static class B {
-
-        long f1 = 0xdeadbeefdeadbe01L;
-        long f2 = 0xdeadbeefdeadbe02L;
-        long f3 = 0xdeadbeefdeadbe03L;
-        long f4 = 0xdeadbeefdeadbe04L;
-        long f5 = 0xdeadbeefdeadbe05L;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewMultiArrayTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +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.replacements;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-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.*;
-
-/**
- * Tests the lowering of the MULTIANEWARRAY instruction.
- */
-public class NewMultiArrayTest extends GraalCompilerTest {
-
-    private static int rank(ResolvedJavaType type) {
-        String name = type.getName();
-        int dims = 0;
-        while (dims < name.length() && name.charAt(dims) == '[') {
-            dims++;
-        }
-        return dims;
-    }
-
-    @Override
-    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        boolean forceCompile = false;
-        if (bottomType != null) {
-            List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
-            assert snapshot != null;
-            assert snapshot.size() == 1;
-
-            NewMultiArrayNode node = snapshot.get(0);
-            assert rank(arrayType) == dimensions.length;
-            int rank = dimensions.length;
-            ValueNode[] dimensionNodes = new ValueNode[rank];
-            for (int i = 0; i < rank; i++) {
-                dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph));
-            }
-
-            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
-            graph.replaceFixedWithFixed(node, repl);
-            forceCompile = true;
-        }
-        return super.getCode(method, graph, forceCompile);
-    }
-
-    @Override
-    protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-        if (bottomType != null) {
-            try {
-                return Array.newInstance(bottomClass, dimensions);
-            } catch (Exception e) {
-                throw new InvocationTargetException(e);
-            }
-        }
-        return super.referenceInvoke(method, receiver, args);
-    }
-
-    ResolvedJavaType arrayType;
-    ResolvedJavaType bottomType;
-    Class bottomClass;
-    int[] dimensions;
-
-    @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;
-            bottomType = runtime.lookupJavaType(clazz);
-            arrayType = bottomType;
-            for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
-                while (rank(arrayType) != rank) {
-                    arrayType = arrayType.getArrayClass();
-                }
-
-                dimensions = new int[rank];
-                for (int i = 0; i < rank; i++) {
-                    dimensions[i] = 1;
-                }
-
-                test("newMultiArray");
-            }
-        }
-        bottomType = null;
-        arrayType = null;
-    }
-
-    public static Object newMultiArray() {
-        // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
-        // This also means we need a separate test for correct handling of negative dimensions
-        // as deoptimization won't do what we want for a graph modified to be different from the
-        // source bytecode.
-        return new Object[10][9][8];
-    }
-
-    @LongTest
-    public void test2() {
-        test("newMultiArrayException");
-    }
-
-    public static Object newMultiArrayException() {
-        return new Object[10][9][-8];
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/PointerTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,399 +0,0 @@
-/*
- * 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.replacements;
-
-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.replacements.Snippet.*;
-import com.oracle.graal.word.*;
-
-/**
- * Tests for the {@link Pointer} read and write operations.
- */
-public class PointerTest extends GraalCompilerTest implements Snippets {
-
-    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 ReplacementsInstaller installer;
-
-    public PointerTest() {
-        target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
-        installer = new ReplacementsInstaller(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.replacements.test/src/com/oracle/graal/replacements/StandardMethodSubstitutionsTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +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.replacements;
-
-import static com.oracle.graal.graph.UnsafeAccess.*;
-import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
-
-import java.lang.reflect.*;
-import java.util.concurrent.atomic.*;
-
-import org.junit.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * Tests the VM independent {@link MethodSubstitution}s.
- */
-public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest {
-
-    static long off(Object o, String name) {
-        try {
-            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
-        } catch (Exception e) {
-            Assert.fail(e.toString());
-            return 0L;
-        }
-    }
-
-    static class Foo {
-
-        boolean z;
-        byte b;
-        short s;
-        char c;
-        int i;
-        long l;
-        float f;
-        double d;
-        Object o;
-
-        void testGet(Field field, long offset, String getName, Object value) throws Exception {
-            field.set(this, value);
-            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
-            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
-            Object expected = m1.invoke(unsafe, this, offset);
-            Object actual = m2.invoke(null, unsafe, this, offset);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testDirect(Field field, long offset, String type, Object value) throws Exception {
-            if (type.equals("Boolean") || type.equals("Object")) {
-                // No direct memory access for these types
-                return;
-            }
-
-            long address = unsafe.allocateMemory(offset + 16);
-
-            String getName = "get" + type;
-            String putName = "put" + type;
-            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
-            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
-
-            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
-
-            m1.invoke(unsafe, address + offset, value);
-            Object expected = m2.invoke(unsafe, address + offset);
-
-            m3.invoke(null, unsafe, address + offset, value);
-            Object actual = m4.invoke(null, unsafe, address + offset);
-
-            unsafe.freeMemory(address);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testPut(Field field, long offset, String putName, Object value) throws Exception {
-            Object initialValue = field.get(new Foo());
-            field.set(this, initialValue);
-
-            try {
-                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
-                m1.invoke(unsafe, this, offset, value);
-                Object expected = field.get(this);
-                m2.invoke(null, unsafe, this, offset, value);
-                Object actual = field.get(this);
-                Assert.assertEquals(expected, actual);
-            } catch (NoSuchMethodException e) {
-                if (!putName.startsWith("putOrdered")) {
-                    throw e;
-                }
-            }
-        }
-
-        void test(String fieldName, String typeSuffix, Object value) {
-            try {
-                Field field = Foo.class.getDeclaredField(fieldName);
-                long offset = unsafe.objectFieldOffset(field);
-                testGet(field, offset, "get" + typeSuffix, value);
-                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "put" + typeSuffix, value);
-                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "putOrdered" + typeSuffix, value);
-                testDirect(field, offset, typeSuffix, value);
-            } catch (Exception e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    @Test
-    public void testUnsafeSubstitutions() throws Exception {
-        test("unsafeCompareAndSwapInt");
-        test("unsafeCompareAndSwapLong");
-        test("unsafeCompareAndSwapObject");
-
-        test("unsafeGetBoolean");
-        test("unsafeGetByte");
-        test("unsafeGetShort");
-        test("unsafeGetChar");
-        test("unsafeGetInt");
-        test("unsafeGetLong");
-        test("unsafeGetFloat");
-        test("unsafeGetDouble");
-        test("unsafeGetObject");
-
-        test("unsafePutBoolean");
-        test("unsafePutByte");
-        test("unsafePutShort");
-        test("unsafePutChar");
-        test("unsafePutInt");
-        test("unsafePutFloat");
-        test("unsafePutDouble");
-        test("unsafePutObject");
-
-        test("unsafeDirectMemoryRead");
-        test("unsafeDirectMemoryWrite");
-
-        AtomicInteger a1 = new AtomicInteger(42);
-        AtomicInteger a2 = new AtomicInteger(42);
-        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
-        assertEquals(a1.get(), a2.get());
-
-        AtomicLong l1 = new AtomicLong(42);
-        AtomicLong l2 = new AtomicLong(42);
-        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
-        assertEquals(l1.get(), l2.get());
-
-        AtomicReference o1 = new AtomicReference<>("42");
-        AtomicReference o2 = new AtomicReference<>("42");
-        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
-        assertEquals(o1.get(), o2.get());
-
-        Foo f1 = new Foo();
-        f1.test("z", "Boolean", Boolean.TRUE);
-        f1.test("b", "Byte", Byte.MIN_VALUE);
-        f1.test("s", "Short", Short.MAX_VALUE);
-        f1.test("c", "Char", '!');
-        f1.test("i", "Int", 1010010);
-        f1.test("f", "Float", -34.5F);
-        f1.test("l", "Long", 99999L);
-        f1.test("d", "Double", 1234.5678D);
-        f1.test("o", "Object", "object");
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
-        unsafe.putBoolean(obj, offset, value);
-        unsafe.putBooleanVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
-        unsafe.putByte(obj, offset, value);
-        unsafe.putByteVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
-        unsafe.putShort(obj, offset, value);
-        unsafe.putShortVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
-        unsafe.putChar(obj, offset, value);
-        unsafe.putCharVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
-        unsafe.putInt(obj, offset, value);
-        unsafe.putIntVolatile(obj, offset, value);
-        unsafe.putOrderedInt(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
-        unsafe.putLong(obj, offset, value);
-        unsafe.putLongVolatile(obj, offset, value);
-        unsafe.putOrderedLong(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
-        unsafe.putFloat(obj, offset, value);
-        unsafe.putFloatVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
-        unsafe.putDouble(obj, offset, value);
-        unsafe.putDoubleVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
-        unsafe.putObject(obj, offset, value);
-        unsafe.putObjectVolatile(obj, offset, value);
-        unsafe.putOrderedObject(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
-        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
-        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
-        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
-        unsafe.putByte(address, value);
-        unsafe.putShort(address, value);
-        unsafe.putChar(address, (char) value);
-        unsafe.putInt(address, value);
-        unsafe.putLong(address, value);
-        unsafe.putFloat(address, value);
-        unsafe.putDouble(address, value);
-    }
-
-    @Test
-    public void testMathSubstitutions() {
-        assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
-        test("math");
-
-        double value = 34567.891D;
-        assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value));
-        assertEquals(Math.log(value), MathSubstitutionsX86.log(value));
-        assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value));
-        assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value));
-        assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value));
-        assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value));
-    }
-
-    @SuppressWarnings("all")
-    public static double mathAbs(double value) {
-        return Math.abs(value);
-    }
-
-    @SuppressWarnings("all")
-    public static double math(double value) {
-        return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value);
-        // Math.exp(value) +
-        // Math.pow(value, 13);
-    }
-
-    @Test
-    public void testIntegerSubstitutions() {
-        assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class);              // Java
-        assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
-        assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
-        assertInGraph(test("integerBitCount"), BitCountNode.class);                      // Java
-
-        for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
-            assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i));
-            assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i));
-            assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i));
-            assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static int integerReverseBytes(int value) {
-        return Integer.reverseBytes(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerNumberOfLeadingZeros(int value) {
-        return Integer.numberOfLeadingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerNumberOfTrailingZeros(int value) {
-        return Integer.numberOfTrailingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerBitCount(int value) {
-        return Integer.bitCount(value);
-    }
-
-    @Test
-    public void testLongSubstitutions() {
-        assertInGraph(test("longReverseBytes"), ReverseBytesNode.class);              // Java
-        assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
-        assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
-        assertInGraph(test("longBitCount"), BitCountNode.class);                      // Java
-
-        for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
-            assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l));
-            assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l));
-            assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l));
-            assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static long longReverseBytes(long value) {
-        return Long.reverseBytes(value);
-    }
-
-    @SuppressWarnings("all")
-    public static long longNumberOfLeadingZeros(long value) {
-        return Long.numberOfLeadingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static long longNumberOfTrailingZeros(long value) {
-        return Long.numberOfTrailingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int longBitCount(long value) {
-        return Long.bitCount(value);
-    }
-
-    @Test
-    public void testFloatSubstitutions() {
-        assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java
-        test("intBitsToFloat");
-    }
-
-    @SuppressWarnings("all")
-    public static int floatToIntBits(float value) {
-        return Float.floatToIntBits(value);
-    }
-
-    @SuppressWarnings("all")
-    public static float intBitsToFloat(int value) {
-        return Float.intBitsToFloat(value);
-    }
-
-    @Test
-    public void testDoubleSubstitutions() {
-        assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java
-        test("longBitsToDouble");
-    }
-
-    @SuppressWarnings("all")
-    public static long doubleToLongBits(double value) {
-        return Double.doubleToLongBits(value);
-    }
-
-    @SuppressWarnings("all")
-    public static double longBitsToDouble(long value) {
-        return Double.longBitsToDouble(value);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/TypeCheckTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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.replacements;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Base class for checkcast and instanceof test classes.
- */
-public abstract class TypeCheckTest extends GraalCompilerTest {
-
-    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
-
-    protected JavaTypeProfile currentProfile;
-
-    @Override
-    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        boolean forceCompile = false;
-        if (currentProfile != null) {
-            replaceProfile(graph, currentProfile);
-            forceCompile = true;
-        }
-        return super.getCode(method, graph, forceCompile);
-    }
-
-    protected JavaTypeProfile profile(Class... types) {
-        if (types.length == 0) {
-            return null;
-        }
-        ProfiledType[] ptypes = new ProfiledType[types.length];
-        for (int i = 0; i < types.length; i++) {
-            ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length);
-        }
-        return new JavaTypeProfile(0.0D, ptypes);
-    }
-
-    protected void test(String name, JavaTypeProfile profile, Object... args) {
-        assert currentProfile == null;
-        currentProfile = profile;
-        try {
-            super.test(name, args);
-        } finally {
-            currentProfile = null;
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/WordTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +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.replacements;
-
-import java.lang.reflect.*;
-
-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.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.word.*;
-
-/**
- * Tests for the {@link Word} type.
- */
-public class WordTest extends GraalCompilerTest implements Snippets {
-
-    private final ReplacementsInstaller installer;
-
-    public WordTest() {
-        TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
-        installer = new ReplacementsInstaller(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());
-    }
-
-    @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};
-        for (long word : words) {
-            test("unsigned_long", word);
-            test("unsigned_int", (int) word);
-            test("signed_long", word);
-            test("signed_int", (int) word);
-        }
-    }
-
-    @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};
-        for (long word : words) {
-            test("unsigned_not", word);
-            test("signed_not", word);
-            for (long addend : words) {
-                test("unsigned_plus_int", word, (int) addend);
-                test("unsigned_minus_int", word, (int) addend);
-                test("unsigned_plus_int", word, -((int) addend));
-                test("unsigned_minus_int", word, -((int) addend));
-                test("unsigned_plus_long", word, addend);
-                test("unsigned_minus_long", word, addend);
-                test("unsigned_plus_long", word, -addend);
-                test("unsigned_minus_long", word, -addend);
-                test("signed_plus_int", word, (int) addend);
-                test("signed_minus_int", word, (int) addend);
-                test("signed_plus_int", word, -((int) addend));
-                test("signed_minus_int", word, -((int) addend));
-                test("signed_plus_long", word, addend);
-                test("signed_minus_long", word, addend);
-                test("signed_plus_long", word, -addend);
-                test("signed_minus_long", word, -addend);
-
-                test("and_int", word, (int) addend);
-                test("or_int", word, (int) addend);
-                test("and_int", word, -((int) addend));
-                test("or_int", word, -((int) addend));
-                test("and_long", word, addend);
-                test("or_long", word, addend);
-                test("and_long", word, -addend);
-                test("or_long", word, -addend);
-            }
-        }
-    }
-
-    @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) {
-            for (long word2 : words) {
-                for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) {
-                    test(method, word1, word2);
-                    test(method, word2, word1);
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static long unsigned_long(long word) {
-        return Word.unsigned(word).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_int(int word) {
-        return Word.unsigned(word).rawValue();
-    }
-
-    @Snippet
-    public static long signed_long(long word) {
-        return Word.signed(word).rawValue();
-    }
-
-    @Snippet
-    public static long signed_int(int word) {
-        return Word.signed(word).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_plus_int(long word, int addend) {
-        return Word.unsigned(word).add(addend).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_minus_int(long word, int addend) {
-        return Word.unsigned(word).subtract(addend).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_plus_long(long word, long addend) {
-        return Word.unsigned(word).add(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_minus_long(long word, long addend) {
-        return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_plus_int(long word, int addend) {
-        return Word.signed(word).add(addend).rawValue();
-    }
-
-    @Snippet
-    public static long signed_minus_int(long word, int addend) {
-        return Word.signed(word).subtract(addend).rawValue();
-    }
-
-    @Snippet
-    public static long signed_plus_long(long word, long addend) {
-        return Word.signed(word).add(Word.signed(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_minus_long(long word, long addend) {
-        return Word.signed(word).subtract(Word.signed(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_not(long word) {
-        return Word.signed(word).not().rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_not(long word) {
-        return Word.unsigned(word).not().rawValue();
-    }
-
-    @Snippet
-    public static boolean aboveOrEqual(long word1, long word2) {
-        return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean above(long word1, long word2) {
-        return Word.unsigned(word1).aboveThan(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean belowOrEqual(long word1, long word2) {
-        return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean below(long word1, long word2) {
-        return Word.unsigned(word1).belowThan(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static long and_int(long word, int addend) {
-        return Word.unsigned(word).and(addend).rawValue();
-    }
-
-    @Snippet
-    public static long or_int(long word, int addend) {
-        return Word.unsigned(word).or(addend).rawValue();
-    }
-
-    @Snippet
-    public static long and_long(long word, long addend) {
-        return Word.unsigned(word).and(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long or_long(long word, long addend) {
-        return Word.unsigned(word).or(Word.unsigned(addend)).rawValue();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,214 @@
+/*
+ * 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.replacements.test;
+
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests the implementation of checkcast, allowing profiling information to be manually specified.
+ */
+public class CheckCastTest extends TypeCheckTest {
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
+        if (ccn != null) {
+            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile));
+            graph.replaceFixedWithFixed(ccn, ccnNew);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("asNumber", profile(), 111);
+        test("asNumber", profile(Integer.class), 111);
+        test("asNumber", profile(Long.class, Short.class), 111);
+        test("asNumberExt", profile(), 111);
+        test("asNumberExt", profile(Integer.class), 111);
+        test("asNumberExt", profile(Long.class, Short.class), 111);
+    }
+
+    @LongTest
+    public void test2() {
+        test("asString", profile(), "111");
+        test("asString", profile(String.class), "111");
+        test("asString", profile(String.class), "111");
+
+        final String nullString = null;
+        test("asString", profile(), nullString);
+        test("asString", profile(String.class), nullString);
+        test("asString", profile(String.class), nullString);
+
+        test("asStringExt", profile(), "111");
+        test("asStringExt", profile(String.class), "111");
+        test("asStringExt", profile(String.class), "111");
+    }
+
+    @LongTest
+    public void test3() {
+        test("asNumber", profile(), "111");
+    }
+
+    @LongTest
+    public void test4() {
+        test("asString", profile(String.class), 111);
+    }
+
+    @LongTest
+    public void test5() {
+        test("asNumberExt", profile(), "111");
+    }
+
+    @LongTest
+    public void test6() {
+        test("asStringExt", profile(String.class), 111);
+    }
+
+    @LongTest
+    public void test7() {
+        Throwable throwable = new Exception();
+        test("asThrowable", profile(), throwable);
+        test("asThrowable", profile(Throwable.class), throwable);
+        test("asThrowable", profile(Exception.class, Error.class), throwable);
+    }
+
+    @LongTest
+    public void test8() {
+        test("arrayStore", new Object[100], "111");
+    }
+
+    @LongTest
+    public void test8_1() {
+        test("arrayFill", new Object[100], "111");
+    }
+
+    public static Number asNumber(Object o) {
+        return (Number) o;
+    }
+
+    public static String asString(Object o) {
+        return (String) o;
+    }
+
+    public static Throwable asThrowable(Object o) {
+        return (Throwable) o;
+    }
+
+    public static ValueNode asValueNode(Object o) {
+        return (ValueNode) o;
+    }
+
+    public static Number asNumberExt(Object o) {
+        Number n = (Number) o;
+        return n.intValue() + 10;
+    }
+
+    public static String asStringExt(Object o) {
+        String s = (String) o;
+        return "#" + s;
+    }
+
+    public static Object[] arrayStore(Object[] arr, Object value) {
+        arr[15] = value;
+        return arr;
+    }
+
+    public static Object[] arrayFill(Object[] arr, Object value) {
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = value;
+        }
+        return arr;
+    }
+
+    static class Depth1 implements Cloneable {
+    }
+
+    static class Depth2 extends Depth1 {
+    }
+
+    static class Depth3 extends Depth2 {
+    }
+
+    static class Depth4 extends Depth3 {
+    }
+
+    static class Depth5 extends Depth4 {
+    }
+
+    static class Depth6 extends Depth5 {
+    }
+
+    static class Depth7 extends Depth6 {
+    }
+
+    static class Depth8 extends Depth7 {
+    }
+
+    static class Depth9 extends Depth8 {
+    }
+
+    static class Depth10 extends Depth9 {
+    }
+
+    static class Depth11 extends Depth10 {
+    }
+
+    static class Depth12 extends Depth11 {
+    }
+
+    static class Depth13 extends Depth12 {
+    }
+
+    static class Depth14 extends Depth12 {
+    }
+
+    public static Depth12 asDepth12(Object o) {
+        return (Depth12) o;
+    }
+
+    public static Depth12[][] asDepth12Arr(Object o) {
+        return (Depth12[][]) o;
+    }
+
+    public static Cloneable asCloneable(Object o) {
+        return (Cloneable) o;
+    }
+
+    @LongTest
+    public void test9() {
+        Object o = new Depth13();
+        test("asDepth12", profile(), o);
+        test("asDepth12", profile(Depth13.class), o);
+        test("asDepth12", profile(Depth13.class, Depth14.class), o);
+    }
+
+    @LongTest
+    public void test10() {
+        Object o = new Depth13[3][];
+        test("asDepth12Arr", o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.replacements.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests compilation of a hot exception handler.
+ */
+public class CompiledExceptionHandlerTest extends GraalCompilerTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        StructuredGraph graph = super.parse(m);
+        int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count();
+        Assert.assertEquals(1, handlers);
+        return graph;
+    }
+
+    private static void raiseException(String s) {
+        throw new RuntimeException(s);
+    }
+
+    @Test
+    public void test1() {
+        // Ensure the profile shows a hot exception
+        for (int i = 0; i < 10000; i++) {
+            test1Snippet("");
+            test1Snippet(null);
+        }
+
+        test("test1Snippet", "a string");
+    }
+
+    public static String test1Snippet(String message) {
+        if (message != null) {
+            try {
+                raiseException(message);
+            } catch (Exception e) {
+                return message;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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.replacements.test;
+
+import com.oracle.graal.test.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests for {@link InstanceOfDynamicNode}.
+ */
+public class InstanceOfDynamicTest extends GraalCompilerTest {
+
+    public static int id(int value) {
+        return value;
+    }
+
+    @LongTest
+    public void test100() {
+        final Object nul = null;
+        test("isStringDynamic", nul);
+        test("isStringDynamic", "object");
+        test("isStringDynamic", Object.class);
+    }
+
+    @LongTest
+    public void test101() {
+        final Object nul = null;
+        test("isStringIntDynamic", nul);
+        test("isStringIntDynamic", "object");
+        test("isStringIntDynamic", Object.class);
+    }
+
+    @LongTest
+    public void test103() {
+        test("isInstanceDynamic", String.class, null);
+        test("isInstanceDynamic", String.class, "object");
+        test("isInstanceDynamic", String.class, Object.class);
+        test("isInstanceDynamic", int.class, null);
+        test("isInstanceDynamic", int.class, "Object");
+        test("isInstanceDynamic", int.class, Object.class);
+    }
+
+    @LongTest
+    public void test104() {
+        test("isInstanceIntDynamic", String.class, null);
+        test("isInstanceIntDynamic", String.class, "object");
+        test("isInstanceIntDynamic", String.class, Object.class);
+        test("isInstanceIntDynamic", int.class, null);
+        test("isInstanceIntDynamic", int.class, "Object");
+        test("isInstanceIntDynamic", int.class, Object.class);
+    }
+
+    public static boolean isStringDynamic(Object o) {
+        return String.class.isInstance(o);
+    }
+
+    public static int isStringIntDynamic(Object o) {
+        if (String.class.isInstance(o)) {
+            return o.toString().length();
+        }
+        return o.getClass().getName().length();
+    }
+
+    public static boolean isInstanceDynamic(Class c, Object o) {
+        return c.isInstance(o);
+    }
+
+    public static int isInstanceIntDynamic(Class c, Object o) {
+        if (c.isInstance(o)) {
+            return o.toString().length();
+        }
+        return o.getClass().getName().length();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,401 @@
+/*
+ * 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.replacements.test;
+
+import java.util.*;
+
+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.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth12;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth13;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth14;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of instanceof, allowing profiling information to be manually specified.
+ */
+public class InstanceOfTest extends TypeCheckTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
+        if (ion != null) {
+            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile));
+            graph.replaceFloating(ion, ionNew);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("isString", profile(), "object");
+        test("isString", profile(String.class), "object");
+
+        test("isString", profile(), Object.class);
+        test("isString", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test2() {
+        test("isStringInt", profile(), "object");
+        test("isStringInt", profile(String.class), "object");
+
+        test("isStringInt", profile(), Object.class);
+        test("isStringInt", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test2_1() {
+        test("isStringIntComplex", profile(), "object");
+        test("isStringIntComplex", profile(String.class), "object");
+
+        test("isStringIntComplex", profile(), Object.class);
+        test("isStringIntComplex", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test3() {
+        Throwable throwable = new Exception();
+        test("isThrowable", profile(), throwable);
+        test("isThrowable", profile(Throwable.class), throwable);
+        test("isThrowable", profile(Exception.class, Error.class), throwable);
+
+        test("isThrowable", profile(), Object.class);
+        test("isThrowable", profile(Throwable.class), Object.class);
+        test("isThrowable", profile(Exception.class, Error.class), Object.class);
+    }
+
+    @LongTest
+    public void test3_1() {
+        onlyFirstIsException(new Exception(), new Error());
+        test("onlyFirstIsException", profile(), new Exception(), new Error());
+        test("onlyFirstIsException", profile(), new Error(), new Exception());
+        test("onlyFirstIsException", profile(), new Exception(), new Exception());
+        test("onlyFirstIsException", profile(), new Error(), new Error());
+    }
+
+    @LongTest
+    public void test4() {
+        Throwable throwable = new Exception();
+        test("isThrowableInt", profile(), throwable);
+        test("isThrowableInt", profile(Throwable.class), throwable);
+        test("isThrowableInt", profile(Exception.class, Error.class), throwable);
+
+        test("isThrowableInt", profile(), Object.class);
+        test("isThrowableInt", profile(Throwable.class), Object.class);
+        test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
+    }
+
+    @LongTest
+    public void test5() {
+        Map map = new HashMap<>();
+        test("isMap", profile(), map);
+        test("isMap", profile(HashMap.class), map);
+        test("isMap", profile(TreeMap.class, HashMap.class), map);
+
+        test("isMap", profile(), Object.class);
+        test("isMap", profile(HashMap.class), Object.class);
+        test("isMap", profile(TreeMap.class, HashMap.class), Object.class);
+        test("isMap", profile(String.class, HashMap.class), Object.class);
+    }
+
+    @LongTest
+    public void test6() {
+        Map map = new HashMap<>();
+        test("isMapInt", profile(), map);
+        test("isMapInt", profile(HashMap.class), map);
+        test("isMapInt", profile(TreeMap.class, HashMap.class), map);
+
+        test("isMapInt", profile(), Object.class);
+        test("isMapInt", profile(HashMap.class), Object.class);
+        test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
+    }
+
+    @LongTest
+    public void test7() {
+        Object o = new Depth13();
+        test("isDepth12", profile(), o);
+        test("isDepth12", profile(Depth13.class), o);
+        test("isDepth12", profile(Depth13.class, Depth14.class), o);
+
+        o = "not a depth";
+        test("isDepth12", profile(), o);
+        test("isDepth12", profile(Depth13.class), o);
+        test("isDepth12", profile(Depth13.class, Depth14.class), o);
+        test("isDepth12", profile(String.class, HashMap.class), o);
+    }
+
+    @LongTest
+    public void test8() {
+        Object o = new Depth13();
+        test("isDepth12Int", profile(), o);
+        test("isDepth12Int", profile(Depth13.class), o);
+        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
+
+        o = "not a depth";
+        test("isDepth12Int", profile(), o);
+        test("isDepth12Int", profile(Depth13.class), o);
+        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
+    }
+
+    public static boolean isString(Object o) {
+        return o instanceof String;
+    }
+
+    public static int isStringInt(Object o) {
+        if (o instanceof String) {
+            return id(1);
+        }
+        return id(0);
+    }
+
+    public static int isStringIntComplex(Object o) {
+        if (o instanceof String || o instanceof Integer) {
+            return id(o instanceof String ? 1 : 0);
+        }
+        return id(0);
+    }
+
+    public static int id(int value) {
+        return value;
+    }
+
+    public static boolean isThrowable(Object o) {
+        return ((Throwable) o) instanceof Exception;
+    }
+
+    public static int onlyFirstIsException(Throwable t1, Throwable t2) {
+        if (t1 instanceof Exception ^ t2 instanceof Exception) {
+            return t1 instanceof Exception ? 1 : -1;
+        }
+        return -1;
+    }
+
+    public static int isThrowableInt(Object o) {
+        int result = o instanceof Throwable ? 4 : 5;
+        if (o instanceof Throwable) {
+            return id(4);
+        }
+        return result;
+    }
+
+    public static boolean isMap(Object o) {
+        return o instanceof Map;
+    }
+
+    public static int isMapInt(Object o) {
+        if (o instanceof Map) {
+            return id(1);
+        }
+        return id(0);
+    }
+
+    public static boolean isDepth12(Object o) {
+        return o instanceof Depth12;
+    }
+
+    public static int isDepth12Int(Object o) {
+        if (o instanceof Depth12) {
+            return id(0);
+        }
+        return id(0);
+    }
+
+    abstract static class MySite {
+
+        final int offset;
+
+        MySite(int offset) {
+            this.offset = offset;
+        }
+    }
+
+    static class MyMark extends MySite {
+
+        MyMark(int offset) {
+            super(offset);
+        }
+    }
+
+    abstract static class MySafepoint extends MySite {
+
+        MySafepoint(int offset) {
+            super(offset);
+        }
+    }
+
+    static class MyCall extends MySafepoint {
+
+        MyCall(int offset) {
+            super(offset);
+        }
+    }
+
+    @LongTest
+    public void test9() {
+        MyCall callAt63 = new MyCall(63);
+        MyMark markAt63 = new MyMark(63);
+        test("compareMySites", callAt63, callAt63);
+        test("compareMySites", callAt63, markAt63);
+        test("compareMySites", markAt63, callAt63);
+        test("compareMySites", markAt63, markAt63);
+    }
+
+    public static int compareMySites(MySite s1, MySite s2) {
+        if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) {
+            return s1 instanceof MyMark ? -1 : 1;
+        }
+        return s1.offset - s2.offset;
+    }
+
+    @LongTest
+    public void test10() {
+        Mark[] noMarks = {};
+        Call callAt63 = new Call(null, 63, 5, true, null);
+        Mark markAt63 = new Mark(63, "1", noMarks);
+        test("compareSites", callAt63, callAt63);
+        test("compareSites", callAt63, markAt63);
+        test("compareSites", markAt63, callAt63);
+        test("compareSites", markAt63, markAt63);
+    }
+
+    public static int compareSites(Site s1, Site s2) {
+        if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+            return s1 instanceof Mark ? -1 : 1;
+        }
+        return s1.pcOffset - s2.pcOffset;
+    }
+
+    /**
+     * This test exists to show the kind of pattern that is be optimizable by
+     * {@code removeIntermediateMaterialization()} in {@link IfNode}.
+     * <p>
+     * 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}.
+     */
+    @LongTest
+    public void test_removeIntermediateMaterialization() {
+        List<String> list = Arrays.asList("1", "2", "3", "4");
+        test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
+        test("removeIntermediateMaterialization", profile(), list, null, "yes", "no");
+        test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no");
+    }
+
+    public static String removeIntermediateMaterialization(List<Object> list, Object e, String a, String b) {
+        boolean test;
+        if (list == null || e == null) {
+            test = false;
+        } else {
+            test = false;
+            for (Object i : list) {
+                if (i.equals(e)) {
+                    test = true;
+                    break;
+                }
+            }
+        }
+        if (test) {
+            return a;
+        }
+        return b;
+    }
+
+    abstract static class A {
+    }
+
+    static class B extends A {
+    }
+
+    static class C extends B {
+    }
+
+    abstract static class D extends C {
+    }
+
+    public static boolean isArrayOfA(Object o) {
+        return o instanceof A[];
+    }
+
+    public static boolean isArrayOfB(Object o) {
+        return o instanceof B[];
+    }
+
+    public static boolean isArrayOfC(Object o) {
+        return o instanceof C[];
+    }
+
+    public static boolean isArrayOfD(Object o) {
+        return o instanceof D[];
+    }
+
+    @LongTest
+    public void testArray() {
+        Object aArray = new A[10];
+        test("isArrayOfA", aArray);
+
+        Object bArray = new B[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+
+        Object cArray = new C[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfA", cArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+        test("isArrayOfB", cArray);
+        test("isArrayOfC", aArray);
+        test("isArrayOfC", bArray);
+        test("isArrayOfC", cArray);
+
+        Object dArray = new D[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfA", cArray);
+        test("isArrayOfA", dArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+        test("isArrayOfB", cArray);
+        test("isArrayOfB", dArray);
+        test("isArrayOfC", aArray);
+        test("isArrayOfC", bArray);
+        test("isArrayOfC", cArray);
+        test("isArrayOfC", dArray);
+        test("isArrayOfD", aArray);
+        test("isArrayOfD", bArray);
+        test("isArrayOfD", cArray);
+        test("isArrayOfD", dArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests the implementation of the snippets for lowering the INVOKE* instructions.
+ */
+public class InvokeTest extends GraalCompilerTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    public interface I {
+
+        String virtualMethod(String s);
+    }
+
+    public static class A implements I {
+
+        final String name = "A";
+
+        public String virtualMethod(String s) {
+            return name + s;
+        }
+    }
+
+    @SuppressWarnings("static-method")
+    private String privateMethod(String s) {
+        return s;
+    }
+
+    @Test
+    public void test1() {
+        test("invokestatic", "a string");
+        test("invokespecialConstructor", "a string");
+        test("invokespecial", this, "a string");
+        test("invokevirtual", new A(), "a string");
+        test("invokevirtual2", new A(), "a string");
+        test("invokeinterface", new A(), "a string");
+        Object[] args = {null};
+        test("invokestatic", args);
+        test("invokespecialConstructor", args);
+        test("invokespecial", null, null);
+        test("invokevirtual", null, null);
+        test("invokevirtual2", null, null);
+        test("invokeinterface", null, null);
+    }
+
+    public static String invokestatic(String s) {
+        return staticMethod(s);
+    }
+
+    public static String staticMethod(String s) {
+        return s;
+    }
+
+    public static String invokespecialConstructor(String s) {
+        return new A().virtualMethod(s);
+    }
+
+    public static String invokespecial(InvokeTest a, String s) {
+        return a.privateMethod(s);
+    }
+
+    public static String invokevirtual(A a, String s) {
+        return a.virtualMethod(s);
+    }
+
+    public static String invokevirtual2(A a, String s) {
+        a.virtualMethod(s);
+        return a.virtualMethod(s);
+    }
+
+    public static String invokeinterface(I i, String s) {
+        return i.virtualMethod(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.replacements.test;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that
+ * there are no remaining invocations in the graph. This is sufficient if the method that is being
+ * substituted is a native method. For Java methods, additional checks are necessary.
+ */
+public abstract class MethodSubstitutionTest extends GraalCompilerTest {
+
+    protected StructuredGraph test(final String snippet) {
+        return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                PhasePlan phasePlan = getDefaultPhasePlan();
+                Assumptions assumptions = new Assumptions(true);
+                new ComputeProbabilityPhase().apply(graph);
+                Debug.dump(graph, "Graph");
+                new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                Debug.dump(graph, "Graph");
+                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                assertNotInGraph(graph, Invoke.class);
+                return graph;
+            }
+        });
+    }
+
+    protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
+        for (Node node : graph.getNodes()) {
+            if (clazz.isInstance(node)) {
+                fail(node.toString());
+            }
+        }
+        return graph;
+    }
+
+    protected static StructuredGraph assertInGraph(StructuredGraph graph, Class<?> clazz) {
+        for (Node node : graph.getNodes()) {
+            if (clazz.isInstance(node)) {
+                return graph;
+            }
+        }
+        fail("Graph does not contain a node of class " + clazz.getName());
+        return graph;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,209 @@
+/*
+ * 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.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.virtual.phases.ea.*;
+
+public class MonitorTest extends GraalCompilerTest {
+
+    @Test
+    public void test0() {
+        test("lockObjectSimple", new Object(), new Object());
+        test("lockObjectSimple", new Object(), null);
+    }
+
+    @Test
+    public void test0_1() {
+        test("lockThisSimple", "test1", new Object());
+        test("lockThisSimple", "test1", null);
+    }
+
+    @Test
+    public void test0_2() {
+        test("lockObjectSimple", null, "test1");
+    }
+
+    @Test
+    public void test1_1() {
+        test("lockObject", new Object(), "test1", new String[1]);
+    }
+
+    @Test
+    public void test1_2() {
+        test("lockObject", null, "test1_1", new String[1]);
+    }
+
+    @Test
+    public void test2() {
+        test("lockThis", "test2", new String[1]);
+    }
+
+    /**
+     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
+     */
+    @Test
+    public void test3() {
+        test("lockLocalObject", "test3", new String[1]);
+    }
+
+    /**
+     * Tests recursive locking of objects which should be biasable.
+     */
+    @Test
+    public void test4() {
+        Chars src = new Chars("1234567890".toCharArray());
+        Chars dst = new Chars(src.data.length);
+        test("copyObj", src, dst, 100);
+    }
+
+    /**
+     * Tests recursive locking of objects which do not appear to be biasable.
+     */
+    @Test
+    public void test5() {
+        char[] src = "1234567890".toCharArray();
+        char[] dst = new char[src.length];
+        test("copyArr", src, dst, 100);
+    }
+
+    /**
+     * Extends {@link #test4()} with contention.
+     */
+    @Test
+    public void test6() {
+        Chars src = new Chars("1234567890".toCharArray());
+        Chars dst = new Chars(src.data.length);
+        int n = Runtime.getRuntime().availableProcessors();
+        testN(n, "copyObj", src, dst, 100);
+    }
+
+    /**
+     * Extends {@link #test5()} with contention.
+     */
+    @Test
+    public void test7() {
+        char[] src = "1234567890".toCharArray();
+        char[] dst = new char[src.length];
+        int n = Runtime.getRuntime().availableProcessors();
+        testN(n, "copyArr", src, dst, 100);
+    }
+
+    private static String setAndGet(String[] box, String value) {
+        synchronized (box) {
+            box[0] = null;
+        }
+
+        // Do a GC while a object is locked (by the caller)
+        System.gc();
+
+        synchronized (box) {
+            box[0] = value;
+        }
+        return box[0];
+    }
+
+    public static Object lockObjectSimple(Object o, Object value) {
+        synchronized (o) {
+            value.hashCode();
+            return value;
+        }
+    }
+
+    public String lockThisSimple(String value, Object o) {
+        synchronized (this) {
+            synchronized (value) {
+                o.hashCode();
+                return value;
+            }
+        }
+    }
+
+    public static String lockObject(Object o, String value, String[] box) {
+        synchronized (o) {
+            return setAndGet(box, value);
+        }
+    }
+
+    public String lockThis(String value, String[] box) {
+        synchronized (this) {
+            return setAndGet(box, value);
+        }
+    }
+
+    public static String lockLocalObject(String value, String[] box) {
+        Object o = new Object();
+        synchronized (o) {
+            return setAndGet(box, value);
+        }
+    }
+
+    static class Chars {
+
+        final char[] data;
+
+        public Chars(int size) {
+            this.data = new char[size];
+        }
+
+        public Chars(char[] data) {
+            this.data = data;
+        }
+    }
+
+    public static String copyObj(Chars src, Chars dst, int n) {
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < src.data.length; i++) {
+                synchronized (src) {
+                    synchronized (dst) {
+                        synchronized (src) {
+                            synchronized (dst) {
+                                dst.data[i] = src.data[i];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return new String(dst.data);
+    }
+
+    public static String copyArr(char[] src, char[] dst, int n) {
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < src.length; i++) {
+                synchronized (src) {
+                    synchronized (dst) {
+                        synchronized (src) {
+                            synchronized (dst) {
+                                dst[i] = src[i];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return new String(dst);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of {@code [A]NEWARRAY}.
+ */
+public class NewArrayTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected instanceof int[]) {
+            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
+        } else if (expected instanceof byte[]) {
+            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
+        } else if (expected instanceof char[]) {
+            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
+        } else if (expected instanceof short[]) {
+            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
+        } else if (expected instanceof float[]) {
+            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
+        } else if (expected instanceof long[]) {
+            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
+        } else if (expected instanceof double[]) {
+            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
+        } else if (expected instanceof Object[]) {
+            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
+        } else {
+            Assert.fail("non-array value encountered: " + expected);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
+            test("new" + type + "Array7");
+            test("new" + type + "ArrayMinus7");
+            test("new" + type + "Array", 7);
+            test("new" + type + "Array", -7);
+            test("new" + type + "Array", Integer.MAX_VALUE);
+            test("new" + type + "Array", Integer.MIN_VALUE);
+        }
+    }
+
+    public static Object newCharArray7() {
+        return new char[7];
+    }
+
+    public static Object newCharArrayMinus7() {
+        return new char[-7];
+    }
+
+    public static Object newCharArray(int length) {
+        return new char[length];
+    }
+
+    public static Object newShortArray7() {
+        return new short[7];
+    }
+
+    public static Object newShortArrayMinus7() {
+        return new short[-7];
+    }
+
+    public static Object newShortArray(int length) {
+        return new short[length];
+    }
+
+    public static Object newFloatArray7() {
+        return new float[7];
+    }
+
+    public static Object newFloatArrayMinus7() {
+        return new float[-7];
+    }
+
+    public static Object newFloatArray(int length) {
+        return new float[length];
+    }
+
+    public static Object newLongArray7() {
+        return new long[7];
+    }
+
+    public static Object newLongArrayMinus7() {
+        return new long[-7];
+    }
+
+    public static Object newLongArray(int length) {
+        return new long[length];
+    }
+
+    public static Object newDoubleArray7() {
+        return new double[7];
+    }
+
+    public static Object newDoubleArrayMinus7() {
+        return new double[-7];
+    }
+
+    public static Object newDoubleArray(int length) {
+        return new double[length];
+    }
+
+    public static Object newIntArray7() {
+        return new int[7];
+    }
+
+    public static Object newIntArrayMinus7() {
+        return new int[-7];
+    }
+
+    public static Object newIntArray(int length) {
+        return new int[length];
+    }
+
+    public static Object newByteArray7() {
+        return new byte[7];
+    }
+
+    public static Object newByteArrayMinus7() {
+        return new byte[-7];
+    }
+
+    public static Object newByteArray(int length) {
+        return new byte[length];
+    }
+
+    public static Object newStringArray7() {
+        return new String[7];
+    }
+
+    public static Object newStringArrayMinus7() {
+        return new String[-7];
+    }
+
+    public static Object newStringArray(int length) {
+        return new String[length];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,249 @@
+/*
+ * 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.replacements.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of {@code NEW}.
+ */
+public class NewInstanceTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+
+        if (expected instanceof Object[]) {
+            Assert.assertTrue(actual instanceof Object[]);
+            Object[] eArr = (Object[]) expected;
+            Object[] aArr = (Object[]) actual;
+            Assert.assertTrue(eArr.length == aArr.length);
+            for (int i = 0; i < eArr.length; i++) {
+                assertEquals(eArr[i], aArr[i]);
+            }
+        } else if (expected.getClass() != Object.class) {
+            try {
+                expected.getClass().getDeclaredMethod("equals", Object.class);
+                super.assertEquals(expected, actual);
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("newObject");
+    }
+
+    @LongTest
+    public void test2() {
+        test("newObjectTwice");
+    }
+
+    public static Object newObject() {
+        return new Object();
+    }
+
+    @LongTest
+    public void test3() {
+        test("newObjectLoop", 100);
+    }
+
+    @LongTest
+    public void test4() {
+        test("newBigObject");
+    }
+
+    @LongTest
+    public void test5() {
+        test("newSomeObject");
+    }
+
+    @LongTest
+    public void test6() {
+        test("newEmptyString");
+    }
+
+    @LongTest
+    public void test7() {
+        test("newString", "value");
+    }
+
+    @LongTest
+    public void test8() {
+        test("newHashMap", 31);
+    }
+
+    @LongTest
+    public void test9() {
+        test("newRegression", true);
+    }
+
+    public static Object[] newObjectTwice() {
+        Object[] res = {new Object(), new Object()};
+        return res;
+    }
+
+    public static Object[] newObjectLoop(int n) {
+        Object[] res = new Object[n];
+        for (int i = 0; i < n; i++) {
+            res[i] = new Object();
+        }
+        return res;
+    }
+
+    public static BigObject newBigObject() {
+        return new BigObject();
+    }
+
+    public static SomeObject newSomeObject() {
+        return new SomeObject();
+    }
+
+    public static String newEmptyString() {
+        return new String();
+    }
+
+    public static String newString(String value) {
+        return new String(value);
+    }
+
+    public static HashMap newHashMap(int initialCapacity) {
+        return new HashMap(initialCapacity);
+    }
+
+    static class SomeObject {
+
+        String name = "o1";
+        HashMap<String, Object> map = new HashMap<>();
+
+        public SomeObject() {
+            map.put(name, this.getClass());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof SomeObject) {
+                SomeObject so = (SomeObject) obj;
+                return so.name.equals(name) && so.map.equals(map);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+    }
+
+    static class BigObject {
+
+        Object f01;
+        Object f02;
+        Object f03;
+        Object f04;
+        Object f05;
+        Object f06;
+        Object f07;
+        Object f08;
+        Object f09;
+        Object f10;
+        Object f12;
+        Object f13;
+        Object f14;
+        Object f15;
+        Object f16;
+        Object f17;
+        Object f18;
+        Object f19;
+        Object f20;
+        Object f21;
+        Object f22;
+        Object f23;
+        Object f24;
+        Object f25;
+        Object f26;
+        Object f27;
+        Object f28;
+        Object f29;
+        Object f30;
+        Object f31;
+        Object f32;
+        Object f33;
+        Object f34;
+        Object f35;
+        Object f36;
+        Object f37;
+        Object f38;
+        Object f39;
+        Object f40;
+        Object f41;
+        Object f42;
+        Object f43;
+        Object f44;
+        Object f45;
+    }
+
+    /**
+     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
+     * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
+     * allocated B object in the true branch overwrote the allocated array. The cause is that
+     * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
+     * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
+     * first place).
+     */
+    public static Object newRegression(boolean condition) {
+        Object result;
+        if (condition) {
+            Object[] arr = {0, 1, 2, 3, 4, 5};
+            result = new B();
+            for (int i = 0; i < arr.length; ++i) {
+                // If the bug exists, the values of arr will now be deadbeef values
+                // and the virtual dispatch will cause a segfault. This can result in
+                // either a VM crash or a spurious NullPointerException.
+                if (arr[i].equals(Integer.valueOf(i))) {
+                    return false;
+                }
+            }
+        } else {
+            result = new B();
+        }
+        return result;
+    }
+
+    static class B {
+
+        long f1 = 0xdeadbeefdeadbe01L;
+        long f2 = 0xdeadbeefdeadbe02L;
+        long f3 = 0xdeadbeefdeadbe03L;
+        long f4 = 0xdeadbeefdeadbe04L;
+        long f5 = 0xdeadbeefdeadbe05L;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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.replacements.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+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.*;
+
+/**
+ * Tests the lowering of the MULTIANEWARRAY instruction.
+ */
+public class NewMultiArrayTest extends GraalCompilerTest {
+
+    private static int rank(ResolvedJavaType type) {
+        String name = type.getName();
+        int dims = 0;
+        while (dims < name.length() && name.charAt(dims) == '[') {
+            dims++;
+        }
+        return dims;
+    }
+
+    @Override
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
+        if (bottomType != null) {
+            List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
+            assert snapshot != null;
+            assert snapshot.size() == 1;
+
+            NewMultiArrayNode node = snapshot.get(0);
+            assert rank(arrayType) == dimensions.length;
+            int rank = dimensions.length;
+            ValueNode[] dimensionNodes = new ValueNode[rank];
+            for (int i = 0; i < rank; i++) {
+                dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph));
+            }
+
+            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
+            graph.replaceFixedWithFixed(node, repl);
+            forceCompile = true;
+        }
+        return super.getCode(method, graph, forceCompile);
+    }
+
+    @Override
+    protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        if (bottomType != null) {
+            try {
+                return Array.newInstance(bottomClass, dimensions);
+            } catch (Exception e) {
+                throw new InvocationTargetException(e);
+            }
+        }
+        return super.referenceInvoke(method, receiver, args);
+    }
+
+    ResolvedJavaType arrayType;
+    ResolvedJavaType bottomType;
+    Class bottomClass;
+    int[] dimensions;
+
+    @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;
+            bottomType = runtime.lookupJavaType(clazz);
+            arrayType = bottomType;
+            for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
+                while (rank(arrayType) != rank) {
+                    arrayType = arrayType.getArrayClass();
+                }
+
+                dimensions = new int[rank];
+                for (int i = 0; i < rank; i++) {
+                    dimensions[i] = 1;
+                }
+
+                test("newMultiArray");
+            }
+        }
+        bottomType = null;
+        arrayType = null;
+    }
+
+    public static Object newMultiArray() {
+        // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
+        // This also means we need a separate test for correct handling of negative dimensions
+        // as deoptimization won't do what we want for a graph modified to be different from the
+        // source bytecode.
+        return new Object[10][9][8];
+    }
+
+    @LongTest
+    public void test2() {
+        test("newMultiArrayException");
+    }
+
+    public static Object newMultiArrayException() {
+        return new Object[10][9][-8];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,400 @@
+/*
+ * 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.replacements.test;
+
+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.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Tests for the {@link Pointer} read and write operations.
+ */
+public class PointerTest extends GraalCompilerTest implements Snippets {
+
+    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 ReplacementsImpl installer;
+
+    public PointerTest() {
+        target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
+        installer = new ReplacementsImpl(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, null, 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.ANY_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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,454 @@
+/*
+ * 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.replacements.test;
+
+import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
+
+import java.lang.reflect.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Tests the VM independent {@link MethodSubstitution}s.
+ */
+public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest {
+
+    static long off(Object o, String name) {
+        try {
+            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
+        } catch (Exception e) {
+            Assert.fail(e.toString());
+            return 0L;
+        }
+    }
+
+    static class Foo {
+
+        boolean z;
+        byte b;
+        short s;
+        char c;
+        int i;
+        long l;
+        float f;
+        double d;
+        Object o;
+
+        void testGet(Field field, long offset, String getName, Object value) throws Exception {
+            field.set(this, value);
+            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
+            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
+            Object expected = m1.invoke(unsafe, this, offset);
+            Object actual = m2.invoke(null, unsafe, this, offset);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testDirect(Field field, long offset, String type, Object value) throws Exception {
+            if (type.equals("Boolean") || type.equals("Object")) {
+                // No direct memory access for these types
+                return;
+            }
+
+            long address = unsafe.allocateMemory(offset + 16);
+
+            String getName = "get" + type;
+            String putName = "put" + type;
+            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
+            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
+
+            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
+
+            m1.invoke(unsafe, address + offset, value);
+            Object expected = m2.invoke(unsafe, address + offset);
+
+            m3.invoke(null, unsafe, address + offset, value);
+            Object actual = m4.invoke(null, unsafe, address + offset);
+
+            unsafe.freeMemory(address);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testPut(Field field, long offset, String putName, Object value) throws Exception {
+            Object initialValue = field.get(new Foo());
+            field.set(this, initialValue);
+
+            try {
+                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
+                m1.invoke(unsafe, this, offset, value);
+                Object expected = field.get(this);
+                m2.invoke(null, unsafe, this, offset, value);
+                Object actual = field.get(this);
+                Assert.assertEquals(expected, actual);
+            } catch (NoSuchMethodException e) {
+                if (!putName.startsWith("putOrdered")) {
+                    throw e;
+                }
+            }
+        }
+
+        void test(String fieldName, String typeSuffix, Object value) {
+            try {
+                Field field = Foo.class.getDeclaredField(fieldName);
+                long offset = unsafe.objectFieldOffset(field);
+                testGet(field, offset, "get" + typeSuffix, value);
+                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "put" + typeSuffix, value);
+                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "putOrdered" + typeSuffix, value);
+                testDirect(field, offset, typeSuffix, value);
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    @Test
+    public void testUnsafeSubstitutions() throws Exception {
+        test("unsafeCompareAndSwapInt");
+        test("unsafeCompareAndSwapLong");
+        test("unsafeCompareAndSwapObject");
+
+        test("unsafeGetBoolean");
+        test("unsafeGetByte");
+        test("unsafeGetShort");
+        test("unsafeGetChar");
+        test("unsafeGetInt");
+        test("unsafeGetLong");
+        test("unsafeGetFloat");
+        test("unsafeGetDouble");
+        test("unsafeGetObject");
+
+        test("unsafePutBoolean");
+        test("unsafePutByte");
+        test("unsafePutShort");
+        test("unsafePutChar");
+        test("unsafePutInt");
+        test("unsafePutFloat");
+        test("unsafePutDouble");
+        test("unsafePutObject");
+
+        test("unsafeDirectMemoryRead");
+        test("unsafeDirectMemoryWrite");
+
+        AtomicInteger a1 = new AtomicInteger(42);
+        AtomicInteger a2 = new AtomicInteger(42);
+        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
+        assertEquals(a1.get(), a2.get());
+
+        AtomicLong l1 = new AtomicLong(42);
+        AtomicLong l2 = new AtomicLong(42);
+        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
+        assertEquals(l1.get(), l2.get());
+
+        AtomicReference o1 = new AtomicReference<>("42");
+        AtomicReference o2 = new AtomicReference<>("42");
+        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
+        assertEquals(o1.get(), o2.get());
+
+        Foo f1 = new Foo();
+        f1.test("z", "Boolean", Boolean.TRUE);
+        f1.test("b", "Byte", Byte.MIN_VALUE);
+        f1.test("s", "Short", Short.MAX_VALUE);
+        f1.test("c", "Char", '!');
+        f1.test("i", "Int", 1010010);
+        f1.test("f", "Float", -34.5F);
+        f1.test("l", "Long", 99999L);
+        f1.test("d", "Double", 1234.5678D);
+        f1.test("o", "Object", "object");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
+        unsafe.putBoolean(obj, offset, value);
+        unsafe.putBooleanVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
+        unsafe.putByte(obj, offset, value);
+        unsafe.putByteVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
+        unsafe.putShort(obj, offset, value);
+        unsafe.putShortVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
+        unsafe.putChar(obj, offset, value);
+        unsafe.putCharVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
+        unsafe.putInt(obj, offset, value);
+        unsafe.putIntVolatile(obj, offset, value);
+        unsafe.putOrderedInt(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
+        unsafe.putLong(obj, offset, value);
+        unsafe.putLongVolatile(obj, offset, value);
+        unsafe.putOrderedLong(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
+        unsafe.putFloat(obj, offset, value);
+        unsafe.putFloatVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
+        unsafe.putDouble(obj, offset, value);
+        unsafe.putDoubleVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
+        unsafe.putObject(obj, offset, value);
+        unsafe.putObjectVolatile(obj, offset, value);
+        unsafe.putOrderedObject(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
+        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
+        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
+        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
+        unsafe.putByte(address, value);
+        unsafe.putShort(address, value);
+        unsafe.putChar(address, (char) value);
+        unsafe.putInt(address, value);
+        unsafe.putLong(address, value);
+        unsafe.putFloat(address, value);
+        unsafe.putDouble(address, value);
+    }
+
+    @Test
+    public void testMathSubstitutions() {
+        assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
+        test("math");
+
+        double value = 34567.891D;
+        assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value));
+        assertEquals(Math.log(value), MathSubstitutionsX86.log(value));
+        assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value));
+        assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value));
+        assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value));
+        assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value));
+    }
+
+    @SuppressWarnings("all")
+    public static double mathAbs(double value) {
+        return Math.abs(value);
+    }
+
+    @SuppressWarnings("all")
+    public static double math(double value) {
+        return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value);
+        // Math.exp(value) +
+        // Math.pow(value, 13);
+    }
+
+    @Test
+    public void testIntegerSubstitutions() {
+        assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class);              // Java
+        assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
+        assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
+        assertInGraph(test("integerBitCount"), BitCountNode.class);                      // Java
+
+        for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
+            assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i));
+            assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i));
+            assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i));
+            assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static int integerReverseBytes(int value) {
+        return Integer.reverseBytes(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerNumberOfLeadingZeros(int value) {
+        return Integer.numberOfLeadingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerNumberOfTrailingZeros(int value) {
+        return Integer.numberOfTrailingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerBitCount(int value) {
+        return Integer.bitCount(value);
+    }
+
+    @Test
+    public void testLongSubstitutions() {
+        assertInGraph(test("longReverseBytes"), ReverseBytesNode.class);              // Java
+        assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
+        assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
+        assertInGraph(test("longBitCount"), BitCountNode.class);                      // Java
+
+        for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
+            assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l));
+            assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l));
+            assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l));
+            assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static long longReverseBytes(long value) {
+        return Long.reverseBytes(value);
+    }
+
+    @SuppressWarnings("all")
+    public static long longNumberOfLeadingZeros(long value) {
+        return Long.numberOfLeadingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static long longNumberOfTrailingZeros(long value) {
+        return Long.numberOfTrailingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int longBitCount(long value) {
+        return Long.bitCount(value);
+    }
+
+    @Test
+    public void testFloatSubstitutions() {
+        assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java
+        test("intBitsToFloat");
+    }
+
+    @SuppressWarnings("all")
+    public static int floatToIntBits(float value) {
+        return Float.floatToIntBits(value);
+    }
+
+    @SuppressWarnings("all")
+    public static float intBitsToFloat(int value) {
+        return Float.intBitsToFloat(value);
+    }
+
+    @Test
+    public void testDoubleSubstitutions() {
+        assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java
+        test("longBitsToDouble");
+    }
+
+    @SuppressWarnings("all")
+    public static long doubleToLongBits(double value) {
+        return Double.doubleToLongBits(value);
+    }
+
+    @SuppressWarnings("all")
+    public static double longBitsToDouble(long value) {
+        return Double.longBitsToDouble(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.replacements.test;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Base class for checkcast and instanceof test classes.
+ */
+public abstract class TypeCheckTest extends GraalCompilerTest {
+
+    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
+
+    protected JavaTypeProfile currentProfile;
+
+    @Override
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
+        if (currentProfile != null) {
+            replaceProfile(graph, currentProfile);
+            forceCompile = true;
+        }
+        return super.getCode(method, graph, forceCompile);
+    }
+
+    protected JavaTypeProfile profile(Class... types) {
+        return profile(TriState.UNKNOWN, types);
+    }
+
+    protected JavaTypeProfile profile(TriState nullSeen, Class... types) {
+        if (types.length == 0) {
+            return null;
+        }
+        ProfiledType[] ptypes = new ProfiledType[types.length];
+        for (int i = 0; i < types.length; i++) {
+            ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length);
+        }
+        return new JavaTypeProfile(nullSeen, 0.0D, ptypes);
+    }
+
+    protected void test(String name, JavaTypeProfile profile, Object... args) {
+        assert currentProfile == null;
+        currentProfile = profile;
+        try {
+            super.test(name, args);
+        } finally {
+            currentProfile = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,228 @@
+/*
+ * 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.replacements.test;
+
+import java.lang.reflect.*;
+
+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.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Tests for the {@link Word} type.
+ */
+public class WordTest extends GraalCompilerTest implements Snippets {
+
+    private final ReplacementsImpl installer;
+
+    public WordTest() {
+        TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
+        installer = new ReplacementsImpl(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, null, inliningPolicy.get());
+    }
+
+    @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};
+        for (long word : words) {
+            test("unsigned_long", word);
+            test("unsigned_int", (int) word);
+            test("signed_long", word);
+            test("signed_int", (int) word);
+        }
+    }
+
+    @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};
+        for (long word : words) {
+            test("unsigned_not", word);
+            test("signed_not", word);
+            for (long addend : words) {
+                test("unsigned_plus_int", word, (int) addend);
+                test("unsigned_minus_int", word, (int) addend);
+                test("unsigned_plus_int", word, -((int) addend));
+                test("unsigned_minus_int", word, -((int) addend));
+                test("unsigned_plus_long", word, addend);
+                test("unsigned_minus_long", word, addend);
+                test("unsigned_plus_long", word, -addend);
+                test("unsigned_minus_long", word, -addend);
+                test("signed_plus_int", word, (int) addend);
+                test("signed_minus_int", word, (int) addend);
+                test("signed_plus_int", word, -((int) addend));
+                test("signed_minus_int", word, -((int) addend));
+                test("signed_plus_long", word, addend);
+                test("signed_minus_long", word, addend);
+                test("signed_plus_long", word, -addend);
+                test("signed_minus_long", word, -addend);
+
+                test("and_int", word, (int) addend);
+                test("or_int", word, (int) addend);
+                test("and_int", word, -((int) addend));
+                test("or_int", word, -((int) addend));
+                test("and_long", word, addend);
+                test("or_long", word, addend);
+                test("and_long", word, -addend);
+                test("or_long", word, -addend);
+            }
+        }
+    }
+
+    @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) {
+            for (long word2 : words) {
+                for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) {
+                    test(method, word1, word2);
+                    test(method, word2, word1);
+                }
+            }
+        }
+    }
+
+    @Snippet
+    public static long unsigned_long(long word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_int(int word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_long(long word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_int(int word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_plus_int(long word, int addend) {
+        return Word.unsigned(word).add(addend).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_int(long word, int addend) {
+        return Word.unsigned(word).subtract(addend).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_plus_long(long word, long addend) {
+        return Word.unsigned(word).add(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_long(long word, long addend) {
+        return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_int(long word, int addend) {
+        return Word.signed(word).add(addend).rawValue();
+    }
+
+    @Snippet
+    public static long signed_minus_int(long word, int addend) {
+        return Word.signed(word).subtract(addend).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_long(long word, long addend) {
+        return Word.signed(word).add(Word.signed(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_minus_long(long word, long addend) {
+        return Word.signed(word).subtract(Word.signed(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_not(long word) {
+        return Word.signed(word).not().rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_not(long word) {
+        return Word.unsigned(word).not().rawValue();
+    }
+
+    @Snippet
+    public static boolean aboveOrEqual(long word1, long word2) {
+        return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean above(long word1, long word2) {
+        return Word.unsigned(word1).aboveThan(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean belowOrEqual(long word1, long word2) {
+        return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean below(long word1, long word2) {
+        return Word.unsigned(word1).belowThan(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static long and_int(long word, int addend) {
+        return Word.unsigned(word).and(addend).rawValue();
+    }
+
+    @Snippet
+    public static long or_int(long word, int addend) {
+        return Word.unsigned(word).or(addend).rawValue();
+    }
+
+    @Snippet
+    public static long and_long(long word, long addend) {
+        return Word.unsigned(word).and(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long or_long(long word, long addend) {
+        return Word.unsigned(word).or(Word.unsigned(addend)).rawValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,243 @@
+/*
+ * 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.replacements;
+
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+
+import java.lang.reflect.*;
+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.Node.NodeIntrinsic;
+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.phases.*;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.word.*;
+
+public class BoxingSnippets implements Snippets {
+
+    /**
+     * This snippet inlining policy differs from the default one in that it does normal inlining of
+     * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution).
+     */
+    public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy {
+
+        @Override
+        public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+            if (Modifier.isNative(method.getModifiers())) {
+                return false;
+            }
+            if (method.getAnnotation(Fold.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(NodeIntrinsic.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(Word.Operation.class) != null) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
+            return false;
+        }
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Boolean booleanValueOf(boolean value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Byte byteValueOf(byte value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Character charValueOf(char value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Double doubleValueOf(double value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Float floatValueOf(float value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Integer intValueOf(int value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Long longValueOf(long value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Short shortValueOf(short value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static boolean booleanValue(Boolean value) {
+        valueOfCounter.inc();
+        return value.booleanValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static byte byteValue(Byte value) {
+        valueOfCounter.inc();
+        return value.byteValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static char charValue(Character value) {
+        valueOfCounter.inc();
+        return value.charValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static double doubleValue(Double value) {
+        valueOfCounter.inc();
+        return value.doubleValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static float floatValue(Float value) {
+        valueOfCounter.inc();
+        return value.floatValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static int intValue(Integer value) {
+        valueOfCounter.inc();
+        return value.intValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static long longValue(Long value) {
+        valueOfCounter.inc();
+        return value.longValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static short shortValue(Short value) {
+        valueOfCounter.inc();
+        return value.shortValue();
+    }
+
+    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) {
+        ValueNode value = box.getValue();
+        if (value.isConstant()) {
+            Constant sourceConstant = value.asConstant();
+            switch (box.getBoxingKind()) {
+                case Boolean:
+                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph());
+                case Byte:
+                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph());
+                case Char:
+                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph());
+                case Short:
+                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph());
+                case Int:
+                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph());
+                case Long:
+                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph());
+                case Float:
+                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph());
+                case Double:
+                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph());
+                default:
+                    assert false : "Unexpected source kind for boxing";
+                    break;
+            }
+        }
+        return null;
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final EnumMap<Kind, SnippetInfo> boxSnippets = new EnumMap<>(Kind.class);
+        private final EnumMap<Kind, SnippetInfo> unboxSnippets = new EnumMap<>(Kind.class);
+
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+            for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) {
+                boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf"));
+                unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value"));
+            }
+        }
+
+        public void lower(BoxNode box) {
+            FloatingNode canonical = canonicalizeBoxing(box, runtime);
+            if (canonical != null) {
+                ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical);
+            } else {
+                Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()));
+                args.add("value", box.getValue());
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args);
+                template.instantiate(runtime, box, DEFAULT_REPLACER, args);
+            }
+        }
+
+        public void lower(UnboxNode unbox) {
+            Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()));
+            args.add("value", unbox.getValue());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args);
+            template.instantiate(runtime, unbox, DEFAULT_REPLACER, args);
+        }
+    }
+
+    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
+    private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,147 @@
+/*
+ * 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.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class BoxingSubstitutions {
+
+    @ClassSubstitution(Boolean.class)
+    private static class BooleanSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Boolean valueOf(boolean value) {
+            return BoxNode.box(value, Boolean.class, Kind.Boolean);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static boolean booleanValue(Boolean value) {
+            return UnboxNode.unbox(value, Kind.Boolean);
+        }
+    }
+
+    @ClassSubstitution(Byte.class)
+    private static class ByteSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Byte valueOf(byte value) {
+            return BoxNode.box(value, Byte.class, Kind.Byte);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static byte byteValue(Byte value) {
+            return UnboxNode.unbox(value, Kind.Byte);
+        }
+    }
+
+    @ClassSubstitution(Character.class)
+    private static class CharacterSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Character valueOf(char value) {
+            return BoxNode.box(value, Character.class, Kind.Char);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static char charValue(Character value) {
+            return UnboxNode.unbox(value, Kind.Char);
+        }
+    }
+
+    @ClassSubstitution(Double.class)
+    private static class DoubleSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Double valueOf(double value) {
+            return BoxNode.box(value, Double.class, Kind.Double);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static double doubleValue(Double value) {
+            return UnboxNode.unbox(value, Kind.Double);
+        }
+    }
+
+    @ClassSubstitution(Float.class)
+    private static class FloatSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Float valueOf(float value) {
+            return BoxNode.box(value, Float.class, Kind.Float);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static float floatValue(Float value) {
+            return UnboxNode.unbox(value, Kind.Float);
+        }
+    }
+
+    @ClassSubstitution(Integer.class)
+    private static class IntegerSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Integer valueOf(int value) {
+            return BoxNode.box(value, Integer.class, Kind.Int);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static int intValue(Integer value) {
+            return UnboxNode.unbox(value, Kind.Int);
+        }
+    }
+
+    @ClassSubstitution(Long.class)
+    private static class LongSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Long valueOf(long value) {
+            return BoxNode.box(value, Long.class, Kind.Long);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static long longValue(Long value) {
+            return UnboxNode.unbox(value, Kind.Long);
+        }
+    }
+
+    @ClassSubstitution(Short.class)
+    private static class ShortSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Short valueOf(short value) {
+            return BoxNode.box(value, Short.class, Kind.Short);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static short shortValue(Short value) {
+            return UnboxNode.unbox(value, Kind.Short);
+        }
+    }
+
+    public static Class<?>[] getClasses() {
+        return new Class<?>[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class,
+                        LongSubstitutions.class, ShortSubstitutions.class};
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Mon Apr 15 08:51:19 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 
 /**
@@ -31,15 +32,19 @@
 @ServiceProvider(ReplacementsProvider.class)
 public class GraalMethodSubstitutions implements ReplacementsProvider {
 
-    public void installReplacements(ReplacementsInstaller installer) {
+    public void registerReplacements(Replacements replacements) {
+        for (Class<?> clazz : BoxingSubstitutions.getClasses()) {
+            replacements.registerSubstitutions(clazz);
+        }
+
         if (GraalOptions.Intrinsify) {
-            installer.installSubstitutions(MathSubstitutionsX86.class);
-            installer.installSubstitutions(DoubleSubstitutions.class);
-            installer.installSubstitutions(FloatSubstitutions.class);
-            installer.installSubstitutions(NodeClassSubstitutions.class);
-            installer.installSubstitutions(LongSubstitutions.class);
-            installer.installSubstitutions(IntegerSubstitutions.class);
-            installer.installSubstitutions(UnsignedMathSubstitutions.class);
+            replacements.registerSubstitutions(MathSubstitutionsX86.class);
+            replacements.registerSubstitutions(DoubleSubstitutions.class);
+            replacements.registerSubstitutions(FloatSubstitutions.class);
+            replacements.registerSubstitutions(NodeClassSubstitutions.class);
+            replacements.registerSubstitutions(LongSubstitutions.class);
+            replacements.registerSubstitutions(IntegerSubstitutions.class);
+            replacements.registerSubstitutions(UnsignedMathSubstitutions.class);
         }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Apr 15 08:51:19 2013 +0200
@@ -34,7 +34,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer;
 
 /**
  * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity
@@ -49,31 +51,16 @@
  * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested
  * by the {@link IfNode}.
  */
-public abstract class InstanceOfSnippetsTemplates<T extends Snippets> extends AbstractTemplates<T> {
+public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates {
 
-    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target, Class<T> snippetsClass) {
-        super(runtime, assumptions, target, snippetsClass);
+    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+        super(runtime, replacements, target);
     }
 
     /**
-     * The key and arguments used to retrieve and instantiate an instanceof snippet template.
+     * Gets the arguments used to retrieve and instantiate an instanceof snippet template.
      */
-    public static class KeyAndArguments {
-
-        public final Key key;
-        public final Arguments arguments;
-
-        public KeyAndArguments(Key key, Arguments arguments) {
-            this.key = key;
-            this.arguments = arguments;
-        }
-
-    }
-
-    /**
-     * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template.
-     */
-    protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
+    protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
 
     public void lower(FloatingNode instanceOf, LoweringTool tool) {
         assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
@@ -90,9 +77,8 @@
                 // No need to re-instantiate the snippet - just re-use its result
                 replacer.replaceUsingInstantiation();
             } else {
-                KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool);
-                SnippetTemplate template = cache.get(keyAndArguments.key, assumptions);
-                template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments);
+                Arguments args = makeArguments(replacer, tool);
+                template(args).instantiate(runtime, instanceOf, replacer, tool, args);
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MacroSubstitution.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.replacements;
-
-import java.lang.annotation.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * Denotes a macro substitute method. This replaces a method invocation with an instance of the
- * specified node class.
- * 
- * A macro substitution can be combined with a normal substitution, so that the macro node can be
- * replaced with the actual substitution code during lowering.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface MacroSubstitution {
-
-    /**
-     * Gets the name of the substituted method.
-     * <p>
-     * If the default value is specified for this element, then the name of the substituted method
-     * is same as the substitute method.
-     */
-    String value() default "";
-
-    /**
-     * Determines if the substituted method is static.
-     */
-    boolean isStatic() default true;
-
-    /**
-     * Gets the {@linkplain MetaUtil#signatureToMethodDescriptor signature} of the substituted
-     * method.
-     * <p>
-     * If the default value is specified for this element, then the signature of the substituted
-     * method is the same as the substitute method.
-     */
-    String signature() default "";
-
-    /**
-     * The node class with which the method invocation should be replaced. It needs to be a subclass
-     * of {@link FixedWithNextNode}, and it is expected to provide a public constructor that takes
-     * an InvokeNode as a parameter. For most cases this class should subclass {@link MacroNode} and
-     * use its constructor.
-     */
-    Class<? extends FixedWithNextNode> macro();
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,22 +22,22 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 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.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.Fold;
 
 /**
  * Replaces calls to {@link NodeIntrinsic}s with nodes and calls to methods annotated with
@@ -46,90 +46,77 @@
 public class NodeIntrinsificationPhase extends Phase {
 
     private final MetaAccessProvider runtime;
-    private final BoxingMethodPool pool;
 
-    public NodeIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) {
+    public NodeIntrinsificationPhase(MetaAccessProvider runtime) {
         this.runtime = runtime;
-        this.pool = pool;
     }
 
     @Override
     protected void run(StructuredGraph graph) {
+        ArrayList<Node> cleanUpReturnList = new ArrayList<>();
         for (Invoke i : graph.getInvokes()) {
             if (i.callTarget() instanceof MethodCallTargetNode) {
-                tryIntrinsify(i);
+                tryIntrinsify(i, cleanUpReturnList);
             }
         }
+
+        for (Node node : cleanUpReturnList) {
+            cleanUpReturnCheckCast(node);
+        }
     }
 
-    public static Class<?>[] signatureToTypes(Signature signature, JavaType receiverType, ResolvedJavaType accessingClass) {
-        int count = signature.getParameterCount(receiverType != null);
-        Class<?>[] result = new Class<?>[count];
-        int j = 0;
-        if (receiverType != null) {
-            result[0] = getMirrorOrFail(receiverType.resolve(accessingClass), Thread.currentThread().getContextClassLoader());
-            j = 1;
-        }
-        for (int i = 0; i + j < result.length; ++i) {
-            result[i + j] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), Thread.currentThread().getContextClassLoader());
-        }
-        return result;
-    }
-
-    private boolean tryIntrinsify(Invoke invoke) {
+    private boolean tryIntrinsify(Invoke invoke, List<Node> cleanUpReturnList) {
         ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod();
         NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
         ResolvedJavaType declaringClass = target.getDeclaringClass();
-        JavaType receiverType = invoke.methodCallTarget().isStatic() ? null : declaringClass;
         if (intrinsic != null) {
             assert target.getAnnotation(Fold.class) == null;
+            assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target;
 
-            // TODO mjj non-static intrinsic?
-            Class<?>[] parameterTypes = signatureToTypes(target.getSignature(), null, declaringClass);
+            ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass);
             ResolvedJavaType returnType = target.getSignature().getReturnType(declaringClass).resolve(declaringClass);
 
             // Prepare the arguments for the reflective constructor call on the node class.
-            Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
+            Constant[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
             if (nodeConstructorArguments == null) {
                 return false;
             }
 
             // Create the new node instance.
-            Class<?> c = getNodeClass(target, intrinsic);
-            Node newInstance = createNodeInstance(runtime, c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments);
+            ResolvedJavaType c = getNodeClass(target, intrinsic);
+            Node newInstance = createNodeInstance(c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments);
 
             // Replace the invoke with the new node.
-            invoke.node().graph().add(newInstance);
+            invoke.asNode().graph().add(newInstance);
             invoke.intrinsify(newInstance);
 
             // Clean up checkcast instructions inserted by javac if the return type is generic.
-            cleanUpReturnCheckCast(newInstance);
+            cleanUpReturnList.add(newInstance);
         } else if (target.getAnnotation(Fold.class) != null) {
-            Class<?>[] parameterTypes = signatureToTypes(target.getSignature(), receiverType, declaringClass);
+            ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass);
 
             // Prepare the arguments for the reflective method call
-            Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
+            Constant[] arguments = prepareArguments(invoke, parameterTypes, target, true);
             if (arguments == null) {
                 return false;
             }
-            Object receiver = null;
+            Constant receiver = null;
             if (!invoke.methodCallTarget().isStatic()) {
                 receiver = arguments[0];
-                arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray();
-                parameterTypes = Arrays.asList(parameterTypes).subList(1, parameterTypes.length).toArray(new Class<?>[parameterTypes.length - 1]);
+                arguments = Arrays.copyOfRange(arguments, 1, arguments.length);
+                parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length);
             }
 
             // Call the method
-            Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, Thread.currentThread().getContextClassLoader()), target.getName(), parameterTypes,
-                            receiver, arguments);
+            Constant constant = target.invoke(receiver, arguments);
 
             if (constant != null) {
                 // Replace the invoke with the result of the call
-                ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.node().graph());
+                ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.asNode().graph());
                 invoke.intrinsify(node);
 
                 // Clean up checkcast instructions inserted by javac if the return type is generic.
-                cleanUpReturnCheckCast(node);
+                cleanUpReturnList.add(node);
             } else {
                 // Remove the invoke
                 invoke.intrinsify(null);
@@ -146,15 +133,15 @@
      * @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) {
+    private Constant[] prepareArguments(Invoke invoke, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
         NodeInputList<ValueNode> arguments = invoke.callTarget().arguments();
-        Object[] reflectionCallArguments = new Object[arguments.size()];
+        Constant[] reflectionCallArguments = new Constant[arguments.size()];
         for (int i = 0; i < reflectionCallArguments.length; ++i) {
             int parameterIndex = i;
             if (!invoke.methodCallTarget().isStatic()) {
                 parameterIndex--;
             }
-            ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
+            ValueNode argument = arguments.get(i);
             if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
                 if (!(argument instanceof ConstantNode)) {
                     return null;
@@ -163,171 +150,63 @@
                 Constant constant = constantNode.asConstant();
                 Object o = constant.asBoxedValue();
                 if (o instanceof Class<?>) {
-                    reflectionCallArguments[i] = runtime.lookupJavaType((Class<?>) o);
-                    parameterTypes[i] = ResolvedJavaType.class;
+                    reflectionCallArguments[i] = Constant.forObject(runtime.lookupJavaType((Class<?>) o));
+                    parameterTypes[i] = runtime.lookupJavaType(ResolvedJavaType.class);
                 } else {
-                    if (parameterTypes[i] == boolean.class) {
-                        reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0);
-                    } else if (parameterTypes[i] == byte.class) {
-                        reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt());
-                    } else if (parameterTypes[i] == short.class) {
-                        reflectionCallArguments[i] = Short.valueOf((short) constant.asInt());
-                    } else if (parameterTypes[i] == char.class) {
-                        reflectionCallArguments[i] = Character.valueOf((char) constant.asInt());
+                    if (parameterTypes[i].getKind() == Kind.Boolean) {
+                        reflectionCallArguments[i] = Constant.forObject(Boolean.valueOf(constant.asInt() != 0));
+                    } else if (parameterTypes[i].getKind() == Kind.Byte) {
+                        reflectionCallArguments[i] = Constant.forObject(Byte.valueOf((byte) constant.asInt()));
+                    } else if (parameterTypes[i].getKind() == Kind.Short) {
+                        reflectionCallArguments[i] = Constant.forObject(Short.valueOf((short) constant.asInt()));
+                    } else if (parameterTypes[i].getKind() == Kind.Char) {
+                        reflectionCallArguments[i] = Constant.forObject(Character.valueOf((char) constant.asInt()));
                     } else {
-                        reflectionCallArguments[i] = o;
+                        reflectionCallArguments[i] = constant;
                     }
                 }
             } else {
-                reflectionCallArguments[i] = argument;
-                parameterTypes[i] = ValueNode.class;
+                reflectionCallArguments[i] = Constant.forObject(argument);
+                parameterTypes[i] = runtime.lookupJavaType(ValueNode.class);
             }
         }
         return reflectionCallArguments;
     }
 
-    private static Class<?> getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
-        Class<?> result = intrinsic.value();
-        if (result == NodeIntrinsic.class) {
-            return getMirrorOrFail(target.getDeclaringClass(), Thread.currentThread().getContextClassLoader());
+    private ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
+        ResolvedJavaType result;
+        if (intrinsic.value() == NodeIntrinsic.class) {
+            result = target.getDeclaringClass();
+        } else {
+            result = runtime.lookupJavaType(intrinsic.value());
         }
-        assert Node.class.isAssignableFrom(result);
+        assert runtime.lookupJavaType(ValueNode.class).isAssignableFrom(result);
         return result;
     }
 
-    private ValueNode tryBoxingElimination(int parameterIndex, ResolvedJavaMethod target, ValueNode node) {
-        if (parameterIndex >= 0) {
-            Type type = target.getGenericParameterTypes()[parameterIndex];
-            if (type instanceof TypeVariable) {
-                TypeVariable typeVariable = (TypeVariable) type;
-                if (typeVariable.getBounds().length == 1) {
-                    Type boundType = typeVariable.getBounds()[0];
-                    if (boundType instanceof Class && ((Class) boundType).getSuperclass() == null) {
-                        // Unbound generic => try boxing elimination
-                        if (node.usages().count() == 2) {
-                            if (node instanceof Invoke) {
-                                Invoke invokeNode = (Invoke) node;
-                                MethodCallTargetNode callTarget = invokeNode.methodCallTarget();
-                                if (pool.isBoxingMethod(callTarget.targetMethod())) {
-                                    FrameState stateAfter = invokeNode.stateAfter();
-                                    assert stateAfter.usages().count() == 1;
-                                    invokeNode.node().replaceAtUsages(null);
-                                    ValueNode result = callTarget.arguments().get(0);
-                                    StructuredGraph graph = (StructuredGraph) node.graph();
-                                    if (invokeNode instanceof InvokeWithExceptionNode) {
-                                        // Destroy exception edge & clear stateAfter.
-                                        InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+    private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) {
+        ResolvedJavaMethod constructor = null;
+        Constant[] arguments = null;
 
-                                        invokeWithExceptionNode.killExceptionEdge();
-                                        graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
-                                    } else {
-                                        graph.removeFixed((InvokeNode) invokeNode);
-                                    }
-                                    stateAfter.safeDelete();
-                                    GraphUtil.propagateKill(callTarget);
-                                    return result;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return node;
-    }
-
-    private static Class asBoxedType(Class type) {
-        if (!type.isPrimitive()) {
-            return type;
-        }
+        for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) {
+            Constant[] match = match(c, parameterTypes, nodeConstructorArguments);
 
-        if (Boolean.TYPE == type) {
-            return Boolean.class;
-        }
-        if (Character.TYPE == type) {
-            return Character.class;
-        }
-        if (Byte.TYPE == type) {
-            return Byte.class;
-        }
-        if (Short.TYPE == type) {
-            return Short.class;
-        }
-        if (Integer.TYPE == type) {
-            return Integer.class;
-        }
-        if (Long.TYPE == type) {
-            return Long.class;
-        }
-        if (Float.TYPE == type) {
-            return Float.class;
-        }
-        assert Double.TYPE == type;
-        return Double.class;
-    }
-
-    static final int VARARGS = 0x00000080;
-
-    private static Node createNodeInstance(MetaAccessProvider runtime, Class<?> nodeClass, Class<?>[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType,
-                    Object[] nodeConstructorArguments) {
-        Object[] arguments = null;
-        Constructor<?> constructor = null;
-        boolean needsMetaAccessProviderArgument = false;
-        nextConstructor: for (Constructor c : nodeClass.getDeclaredConstructors()) {
-            needsMetaAccessProviderArgument = false;
-            Class[] signature = c.getParameterTypes();
-            if (signature.length != 0 && signature[0] == MetaAccessProvider.class) {
-                // Chop off the MetaAccessProvider first parameter
-                signature = Arrays.copyOfRange(signature, 1, signature.length);
-                needsMetaAccessProviderArgument = true;
-            }
-            if ((c.getModifiers() & VARARGS) != 0) {
-                int fixedArgs = signature.length - 1;
-                if (parameterTypes.length < fixedArgs) {
-                    continue nextConstructor;
+            if (match != null) {
+                if (constructor == null) {
+                    constructor = c;
+                    arguments = match;
+                } else {
+                    throw new GraalInternalError("Found multiple constructors in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes) + ": " + constructor + ", " + c);
                 }
-
-                for (int i = 0; i < fixedArgs; i++) {
-                    if (!parameterTypes[i].equals(signature[i])) {
-                        continue nextConstructor;
-                    }
-                }
-
-                Class componentType = signature[fixedArgs].getComponentType();
-                assert componentType != null : "expected last parameter of varargs constructor " + c + " to be an array type";
-                Class boxedType = asBoxedType(componentType);
-                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                    if (!boxedType.isInstance(nodeConstructorArguments[i])) {
-                        continue nextConstructor;
-                    }
-                }
-                arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
-                int varargsLength = nodeConstructorArguments.length - fixedArgs;
-                Object varargs = Array.newInstance(componentType, varargsLength);
-                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                    Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]);
-                }
-                arguments[fixedArgs] = varargs;
-                constructor = c;
-                break;
-            } else if (Arrays.equals(parameterTypes, signature)) {
-                arguments = nodeConstructorArguments;
-                constructor = c;
-                break;
             }
         }
         if (constructor == null) {
             throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes));
         }
-        if (needsMetaAccessProviderArgument) {
-            Object[] copy = new Object[arguments.length + 1];
-            System.arraycopy(arguments, 0, copy, 1, arguments.length);
-            copy[0] = runtime;
-            arguments = copy;
-        }
-        constructor.setAccessible(true);
+
         try {
-            ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments);
+            ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject();
+
             if (setStampFromReturnType) {
                 if (returnType.getKind() == Kind.Object) {
                     intrinsicNode.setStamp(StampFactory.declared(returnType));
@@ -341,26 +220,58 @@
         }
     }
 
-    /**
-     * Calls a Java method via reflection.
-     */
-    private static Constant callMethod(Kind returnKind, Class<?> holder, String name, Class<?>[] parameterTypes, Object receiver, Object[] arguments) {
-        Method method;
-        try {
-            method = holder.getDeclaredMethod(name, parameterTypes);
-            method.setAccessible(true);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+    private Constant[] match(ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) {
+        Constant[] arguments = null;
+        boolean needsMetaAccessProviderArgument = false;
+
+        ResolvedJavaType[] signature = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(c.getSignature(), null), c.getDeclaringClass());
+        if (signature.length != 0 && signature[0].equals(runtime.lookupJavaType(MetaAccessProvider.class))) {
+            // Chop off the MetaAccessProvider first parameter
+            signature = Arrays.copyOfRange(signature, 1, signature.length);
+            needsMetaAccessProviderArgument = true;
         }
-        try {
-            Object result = method.invoke(receiver, arguments);
-            if (result == null) {
+
+        if (Arrays.equals(parameterTypes, signature)) {
+            // Exact match
+            arguments = nodeConstructorArguments;
+
+        } else if (signature.length > 0 && signature[signature.length - 1].isArray()) {
+            // Last constructor parameter is an array, so check if we have a vararg match
+            int fixedArgs = signature.length - 1;
+            if (parameterTypes.length < fixedArgs) {
                 return null;
             }
-            return Constant.forBoxed(returnKind, result);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+            for (int i = 0; i < fixedArgs; i++) {
+                if (!parameterTypes[i].equals(signature[i])) {
+                    return null;
+                }
+            }
+
+            ResolvedJavaType componentType = signature[fixedArgs].getComponentType();
+            assert componentType != null;
+            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                if (!parameterTypes[i].equals(componentType)) {
+                    return null;
+                }
+            }
+            arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
+            arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs);
+
+            Object varargs = arguments[fixedArgs].asObject();
+            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i].asBoxedValue());
+            }
+        } else {
+            return null;
         }
+
+        if (needsMetaAccessProviderArgument) {
+            Constant[] copy = new Constant[arguments.length + 1];
+            System.arraycopy(arguments, 0, copy, 1, arguments.length);
+            copy[0] = Constant.forObject(runtime);
+            arguments = copy;
+        }
+        return arguments;
     }
 
     private static String sourceLocation(Node n) {
@@ -379,32 +290,25 @@
                     if (checkCastUsage instanceof ValueAnchorNode) {
                         ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
                         graph.removeFixed(valueAnchorNode);
+                    } else if (checkCastUsage instanceof UnboxNode) {
+                        UnboxNode unbox = (UnboxNode) checkCastUsage;
+                        unbox.replaceAtUsages(newInstance);
+                        graph.removeFixed(unbox);
                     } else if (checkCastUsage instanceof MethodCallTargetNode) {
                         MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                        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());
-                            } else {
-                                graph.removeFixed((InvokeNode) invokeNode);
-                            }
-                            checkCastCallTarget.safeDelete();
-                        } else {
-                            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());
-                        }
+                        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());
                     } else if (checkCastUsage instanceof FrameState) {
                         checkCastUsage.replaceFirstInput(checkCastNode, null);
                     } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) {
                         checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
+                    } else if (checkCastUsage instanceof IsNullNode) {
+                        assert checkCastUsage.usages().count() == 1 && checkCastUsage.usages().first().predecessor() == checkCastNode;
+                        graph.replaceFloating((FloatingNode) checkCastUsage, LogicConstantNode.contradiction(graph));
                     } else {
+                        Debug.dump(graph, "exception");
                         assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode);
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,483 @@
+/*
+ * 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.replacements;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+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.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.word.phases.*;
+
+public class ReplacementsImpl implements Replacements {
+
+    protected final MetaAccessProvider runtime;
+    protected final TargetDescription target;
+    protected final Assumptions assumptions;
+
+    /**
+     * The preprocessed replacement graphs.
+     */
+    private final ConcurrentMap<ResolvedJavaMethod, StructuredGraph> graphs;
+
+    // These data structures are all fully initialized during single-threaded
+    // compiler startup and so do not need to be concurrent.
+    private final Map<ResolvedJavaMethod, ResolvedJavaMethod> registeredMethodSubstitutions;
+    private final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> registerMacroSubstitutions;
+    private final Set<ResolvedJavaMethod> forcedSubstitutions;
+
+    public ReplacementsImpl(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target) {
+        this.runtime = runtime;
+        this.target = target;
+        this.assumptions = assumptions;
+        this.graphs = new ConcurrentHashMap<>();
+        this.registeredMethodSubstitutions = new HashMap<>();
+        this.registerMacroSubstitutions = new HashMap<>();
+        this.forcedSubstitutions = new HashSet<>();
+    }
+
+    public StructuredGraph getSnippet(ResolvedJavaMethod method) {
+        assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native";
+
+        StructuredGraph graph = graphs.get(method);
+        if (graph == null) {
+            graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method)));
+            graph = graphs.get(method);
+        }
+        return graph;
+    }
+
+    public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) {
+        ResolvedJavaMethod substitute = registeredMethodSubstitutions.get(original);
+        if (substitute == null) {
+            return null;
+        }
+        StructuredGraph graph = graphs.get(substitute);
+        if (graph == null) {
+            graphs.putIfAbsent(substitute, makeGraph(substitute, original, inliningPolicy(substitute)));
+            graph = graphs.get(substitute);
+        }
+        return graph;
+
+    }
+
+    public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
+        return registerMacroSubstitutions.get(method);
+    }
+
+    public Assumptions getAssumptions() {
+        return assumptions;
+    }
+
+    public void registerSubstitutions(Class<?> substitutions) {
+        ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class);
+        assert classSubstitution != null;
+        assert !Snippets.class.isAssignableFrom(substitutions);
+        for (Method substituteMethod : substitutions.getDeclaredMethods()) {
+            MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class);
+            MacroSubstitution macroSubstitution = substituteMethod.getAnnotation(MacroSubstitution.class);
+            if (methodSubstitution == null && macroSubstitution == null) {
+                continue;
+            }
+
+            int modifiers = substituteMethod.getModifiers();
+            if (!Modifier.isStatic(modifiers)) {
+                throw new RuntimeException("Substitution methods must be static: " + substituteMethod);
+            }
+
+            if (methodSubstitution != null) {
+                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+                    throw new RuntimeException("Substitution method must not be abstract or native: " + substituteMethod);
+                }
+                String originalName = originalName(substituteMethod, methodSubstitution.value());
+                Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
+                Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalParameters);
+                if (originalMethod != null) {
+                    ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod);
+                    if (original != null && methodSubstitution.forced()) {
+                        forcedSubstitutions.add(original);
+                    }
+                }
+            }
+            if (macroSubstitution != null) {
+                String originalName = originalName(substituteMethod, macroSubstitution.value());
+                Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
+                Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalParameters);
+                if (originalMethod != null) {
+                    ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro());
+                    if (original != null && macroSubstitution.forced()) {
+                        forcedSubstitutions.add(original);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Registers a method substitution.
+     * 
+     * @param originalMember a method or constructor being substituted
+     * @param substituteMethod the substitute method
+     * @return the original method
+     */
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMember, Method substituteMethod) {
+        ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod);
+        ResolvedJavaMethod original;
+        if (originalMember instanceof Method) {
+            original = runtime.lookupJavaMethod((Method) originalMember);
+        } else {
+            original = runtime.lookupJavaConstructor((Constructor) originalMember);
+        }
+        Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
+
+        registeredMethodSubstitutions.put(original, substitute);
+        return original;
+    }
+
+    /**
+     * Registers a macro substitution.
+     * 
+     * @param originalMethod a method or constructor being substituted
+     * @param macro the substitute macro node class
+     * @return the original method
+     */
+    protected ResolvedJavaMethod registerMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
+        ResolvedJavaMethod originalJavaMethod;
+        if (originalMethod instanceof Method) {
+            originalJavaMethod = runtime.lookupJavaMethod((Method) originalMethod);
+        } else {
+            originalJavaMethod = runtime.lookupJavaConstructor((Constructor) originalMethod);
+        }
+        registerMacroSubstitutions.put(originalJavaMethod, macro);
+        return originalJavaMethod;
+    }
+
+    private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
+        Class<? extends SnippetInliningPolicy> policyClass = SnippetInliningPolicy.class;
+        Snippet snippet = method.getAnnotation(Snippet.class);
+        if (snippet != null) {
+            policyClass = snippet.inlining();
+        }
+        if (policyClass == SnippetInliningPolicy.class) {
+            return new DefaultSnippetInliningPolicy(runtime);
+        }
+        try {
+            return policyClass.getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    /**
+     * Creates a preprocessed graph for a snippet or method substitution.
+     * 
+     * @param method the snippet or method substitution for which a graph will be created
+     * @param original the original method if {@code method} is a {@linkplain MethodSubstitution
+     *            substitution} otherwise null
+     * @param policy the inlining policy to use during preprocessing
+     */
+    public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, SnippetInliningPolicy policy) {
+        return createGraphMaker(method, original).makeGraph(policy);
+    }
+
+    /**
+     * Can be overridden to return an object that specializes various parts of graph preprocessing.
+     */
+    protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original) {
+        return new GraphMaker(substitute, original);
+    }
+
+    /**
+     * Cache to speed up preprocessing of replacement graphs.
+     */
+    final ConcurrentMap<ResolvedJavaMethod, StructuredGraph> graphCache = new ConcurrentHashMap<>();
+
+    /**
+     * Creates and preprocesses a graph for a replacement.
+     */
+    protected class GraphMaker {
+
+        /**
+         * The method for which a graph is being created.
+         */
+        protected final ResolvedJavaMethod method;
+
+        /**
+         * The original method if {@link #method} is a {@linkplain MethodSubstitution substitution}
+         * otherwise null.
+         */
+        protected final ResolvedJavaMethod original;
+
+        boolean substituteCallsOriginal;
+
+        protected GraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original) {
+            this.method = substitute;
+            this.original = original;
+        }
+
+        public StructuredGraph makeGraph(final SnippetInliningPolicy policy) {
+            return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() {
+
+                @Override
+                public StructuredGraph call() throws Exception {
+                    StructuredGraph graph = parseGraph(method, policy);
+
+                    // Cannot have a finalized version of a graph in the cache
+                    graph = graph.copy();
+
+                    finalizeGraph(graph);
+
+                    Debug.dump(graph, "%s: Final", method.getName());
+
+                    return graph;
+                }
+            });
+        }
+
+        /**
+         * Does final processing of a snippet graph.
+         */
+        protected void finalizeGraph(StructuredGraph graph) {
+            new NodeIntrinsificationPhase(runtime).apply(graph);
+            assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph);
+
+            if (original == null) {
+                new SnippetFrameStateCleanupPhase().apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new InsertStateAfterPlaceholderPhase().apply(graph);
+            } else {
+                new DeadCodeEliminationPhase().apply(graph);
+            }
+        }
+
+        private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) {
+            StructuredGraph graph = graphCache.get(methodToParse);
+            if (graph == null) {
+                graphCache.putIfAbsent(methodToParse, buildGraph(methodToParse, policy == null ? inliningPolicy(methodToParse) : policy));
+                graph = graphCache.get(methodToParse);
+                assert graph != null;
+            }
+            return graph;
+        }
+
+        /**
+         * Builds the initial graph for a snippet.
+         */
+        protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod methodToParse) {
+            final StructuredGraph graph = new StructuredGraph(methodToParse);
+            GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
+            GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
+            graphBuilder.apply(graph);
+
+            Debug.dump(graph, "%s: %s", methodToParse.getName(), GraphBuilderPhase.class.getSimpleName());
+
+            new WordTypeVerificationPhase(runtime, target.wordKind).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.Instance(runtime, assumptions).apply(caller);
+            }
+        }
+
+        /**
+         * Called after all inlining for a given graph is complete.
+         */
+        protected void afterInlining(StructuredGraph graph) {
+            new NodeIntrinsificationPhase(runtime).apply(graph);
+
+            new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
+
+            new DeadCodeEliminationPhase().apply(graph);
+            if (GraalOptions.OptCanonicalizer) {
+                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+            }
+        }
+
+        private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) {
+            assert !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers()) : methodToParse;
+            final StructuredGraph graph = buildInitialGraph(methodToParse);
+
+            for (Invoke invoke : graph.getInvokes()) {
+                MethodCallTargetNode callTarget = invoke.methodCallTarget();
+                ResolvedJavaMethod callee = callTarget.targetMethod();
+                if (callee == method) {
+                    final StructuredGraph originalGraph = new StructuredGraph(original);
+                    new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph);
+                    InliningUtil.inline(invoke, originalGraph, true);
+
+                    Debug.dump(graph, "after inlining %s", callee);
+                    afterInline(graph, originalGraph);
+                    substituteCallsOriginal = true;
+                } else {
+                    if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, methodToParse)) {
+                        StructuredGraph targetGraph;
+                        StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee);
+                        if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) {
+                            targetGraph = intrinsicGraph;
+                        } else {
+                            targetGraph = parseGraph(callee, policy);
+                        }
+                        InliningUtil.inline(invoke, targetGraph, true);
+                        Debug.dump(graph, "after inlining %s", callee);
+                        afterInline(graph, targetGraph);
+                    }
+                }
+            }
+
+            afterInlining(graph);
+
+            for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
+                end.disableSafepoint();
+            }
+
+            if (GraalOptions.ProbabilityAnalysis) {
+                new DeadCodeEliminationPhase().apply(graph);
+                new ComputeProbabilityPhase().apply(graph);
+            }
+            return graph;
+        }
+    }
+
+    private static String originalName(Method substituteMethod, String methodSubstitution) {
+        if (methodSubstitution.isEmpty()) {
+            return substituteMethod.getName();
+        } else {
+            return methodSubstitution;
+        }
+    }
+
+    /**
+     * 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
+     */
+    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);
+        }
+    }
+
+    private static Class resolveType(JavaType type) {
+        JavaType base = type;
+        int dimensions = 0;
+        while (base.getComponentType() != null) {
+            base = base.getComponentType();
+            dimensions++;
+        }
+
+        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
+        return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
+    }
+
+    private Class[] originalParameters(Method substituteMethod, String methodSubstitution, boolean isStatic) {
+        Class[] parameters;
+        if (methodSubstitution.isEmpty()) {
+            parameters = substituteMethod.getParameterTypes();
+            if (!isStatic) {
+                assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter";
+                parameters = Arrays.copyOfRange(parameters, 1, parameters.length);
+            }
+        } else {
+            Signature signature = runtime.parseMethodDescriptor(methodSubstitution);
+            parameters = new Class[signature.getParameterCount(false)];
+            for (int i = 0; i < parameters.length; i++) {
+                parameters[i] = resolveType(signature.getParameterType(i, null));
+            }
+        }
+        return parameters;
+    }
+
+    private static Member originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, Class[] parameters) {
+        Class<?> originalClass = classSubstitution.value();
+        if (originalClass == ClassSubstitution.class) {
+            originalClass = resolveType(classSubstitution.className(), classSubstitution.optional());
+            if (originalClass == null) {
+                // optional class was not found
+                return null;
+            }
+        }
+        try {
+            if (name.equals("<init>")) {
+                return originalClass.getDeclaredConstructor(parameters);
+            } else {
+                return originalClass.getDeclaredMethod(name, parameters);
+            }
+        } catch (NoSuchMethodException | SecurityException e) {
+            if (optional) {
+                return null;
+            }
+            throw new GraalInternalError(e);
+        }
+    }
+
+    @Override
+    public Collection<ResolvedJavaMethod> getAllReplacements() {
+        HashSet<ResolvedJavaMethod> result = new HashSet<>();
+        result.addAll(registeredMethodSubstitutions.keySet());
+        result.addAll(registerMacroSubstitutions.keySet());
+        return result;
+    }
+
+    @Override
+    public boolean isForcedSubstitution(ResolvedJavaMethod method) {
+        return forcedSubstitutions.contains(method);
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsInstaller.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +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.replacements;
-
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.java.*;
-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.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
-import com.oracle.graal.word.phases.*;
-
-/**
- * Utility for managing the pre-processing and installation of replacements. Replacements are either
- * {@linkplain Snippets snippets}, {@linkplain MethodSubstitution method substitutions} or
- * {@link MacroSubstitution macro substitutions}.
- */
-public class ReplacementsInstaller {
-
-    protected final MetaAccessProvider runtime;
-    protected final TargetDescription target;
-    protected final Assumptions assumptions;
-    protected final BoxingMethodPool pool;
-    private final Thread owner;
-
-    /**
-     * A graph cache used by this installer to avoid using the compiler storage for each method
-     * processed during snippet installation. Without this, all processed methods are to be
-     * determined as {@linkplain InliningUtil#canIntrinsify intrinsifiable}.
-     */
-    private final Map<ResolvedJavaMethod, StructuredGraph> graphCache;
-
-    public ReplacementsInstaller(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target) {
-        this.runtime = runtime;
-        this.target = target;
-        this.assumptions = assumptions;
-        this.pool = new BoxingMethodPool(runtime);
-        this.graphCache = new HashMap<>();
-        this.owner = Thread.currentThread();
-    }
-
-    /**
-     * Finds all the snippet methods in a given class, builds a graph for them and installs the
-     * graph with the key value of {@code Snippet.class} in the
-     * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of each method.
-     */
-    public void installSnippets(Class<? extends Snippets> snippets) {
-        for (Method method : snippets.getDeclaredMethods()) {
-            if (method.getAnnotation(Snippet.class) != null) {
-                int modifiers = method.getModifiers();
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Snippet must not be abstract or native");
-                }
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
-                assert snippet.getCompilerStorage().get(Snippet.class) == null : method;
-                StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
-                // System.out.println("snippet: " + graph);
-                snippet.getCompilerStorage().put(Snippet.class, graph);
-            }
-        }
-    }
-
-    /**
-     * Finds all the methods in a given class annotated with {@link MethodSubstitution} or
-     * {@link MacroSubstitution}. It builds graphs for the former and installs them in the
-     * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of the original (i.e.,
-     * substituted) method with a key of {@code MethodSubstitution.class}. For the latter, the
-     * denoted {@linkplain MacroSubstitution#macro() macro} node type is install in the compiler
-     * storage with a key of {@code Node.class}.
-     */
-    public void installSubstitutions(Class<?> substitutions) {
-        assert owner == Thread.currentThread() : "substitution installation must be single threaded";
-        ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class);
-        assert classSubstitution != null;
-        assert !Snippets.class.isAssignableFrom(substitutions);
-        for (Method substituteMethod : substitutions.getDeclaredMethods()) {
-            MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class);
-            MacroSubstitution macroSubstitution = substituteMethod.getAnnotation(MacroSubstitution.class);
-            if (methodSubstitution == null && macroSubstitution == null) {
-                continue;
-            }
-
-            int modifiers = substituteMethod.getModifiers();
-            if (!Modifier.isStatic(modifiers)) {
-                throw new RuntimeException("Substitution methods must be static: " + substituteMethod);
-            }
-
-            if (methodSubstitution != null) {
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Substitution method must not be abstract or native: " + substituteMethod);
-                }
-                String originalName = originalName(substituteMethod, methodSubstitution.value());
-                Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
-                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());
-                Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
-                if (originalMethod != null) {
-                    installMacroSubstitution(originalMethod, macroSubstitution.macro());
-                }
-            }
-        }
-    }
-
-    // These fields are used to detect calls from the substitute method to the original method.
-    ResolvedJavaMethod substitute;
-    ResolvedJavaMethod original;
-    boolean substituteCallsOriginal;
-
-    /**
-     * Installs a method substitution.
-     * 
-     * @param originalMember a method or constructor being substituted
-     * @param substituteMethod the substitute method
-     */
-    protected void installMethodSubstitution(Member originalMember, Method substituteMethod) {
-        substitute = runtime.lookupJavaMethod(substituteMethod);
-        if (originalMember instanceof Method) {
-            original = runtime.lookupJavaMethod((Method) originalMember);
-        } else {
-            original = runtime.lookupJavaConstructor((Constructor) originalMember);
-        }
-        try {
-            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(MethodSubstitution.class, graph);
-            assert oldValue == null;
-        } finally {
-            substitute = null;
-            original = null;
-            substituteCallsOriginal = false;
-        }
-    }
-
-    /**
-     * Installs a macro substitution.
-     * 
-     * @param originalMethod a method or constructor being substituted
-     * @param macro the substitute macro node class
-     */
-    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;
-    }
-
-    private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
-        Class<? extends SnippetInliningPolicy> policyClass = SnippetInliningPolicy.class;
-        Snippet snippet = method.getAnnotation(Snippet.class);
-        if (snippet != null) {
-            policyClass = snippet.inlining();
-        }
-        if (policyClass == SnippetInliningPolicy.class) {
-            return new DefaultSnippetInliningPolicy(runtime, pool);
-        }
-        try {
-            return policyClass.getConstructor().newInstance();
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    /**
-     * Does final processing of a snippet graph.
-     */
-    protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) {
-        new NodeIntrinsificationPhase(runtime, pool).apply(graph);
-        assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph);
-
-        if (substitute == null) {
-            new SnippetFrameStateCleanupPhase().apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new InsertStateAfterPlaceholderPhase().apply(graph);
-        } else {
-            new DeadCodeEliminationPhase().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);
-
-                finalizeGraph(method, graph);
-
-                Debug.dump(graph, "%s: Final", method.getName());
-
-                return graph;
-            }
-        });
-    }
-
-    private StructuredGraph parseGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
-        StructuredGraph graph = graphCache.get(method);
-        if (graph == null) {
-            graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy);
-            graphCache.put(method, graph);
-        }
-        return graph;
-    }
-
-    /**
-     * 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);
-        graphBuilder.apply(graph);
-
-        Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
-
-        new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
-        new NodeIntrinsificationPhase(runtime, pool).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 NodeIntrinsificationPhase(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();
-            ResolvedJavaMethod callee = callTarget.targetMethod();
-            if (callee == substitute) {
-                final StructuredGraph originalGraph = new StructuredGraph(original);
-                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph);
-                InliningUtil.inline(invoke, originalGraph, true);
-
-                Debug.dump(graph, "after inlining %s", callee);
-                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);
-                    afterInline(graph, targetGraph);
-                }
-            }
-        }
-
-        afterInlining(graph);
-
-        for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
-            end.disableSafepoint();
-        }
-
-        if (GraalOptions.ProbabilityAnalysis) {
-            new DeadCodeEliminationPhase().apply(graph);
-            new ComputeProbabilityPhase().apply(graph);
-        }
-        return graph;
-    }
-
-    private static String originalName(Method substituteMethod, String methodSubstitution) {
-        if (methodSubstitution.isEmpty()) {
-            return substituteMethod.getName();
-        } else {
-            return methodSubstitution;
-        }
-    }
-
-    /**
-     * 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
-     */
-    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);
-        }
-    }
-
-    private static Class resolveType(JavaType type) {
-        JavaType base = type;
-        int dimensions = 0;
-        while (base.getComponentType() != null) {
-            base = base.getComponentType();
-            dimensions++;
-        }
-
-        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
-        return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
-    }
-
-    private Class[] originalParameters(Method substituteMethod, String methodSubstitution, boolean isStatic) {
-        Class[] parameters;
-        if (methodSubstitution.isEmpty()) {
-            parameters = substituteMethod.getParameterTypes();
-            if (!isStatic) {
-                assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter";
-                parameters = Arrays.copyOfRange(parameters, 1, parameters.length);
-            }
-        } else {
-            Signature signature = runtime.parseMethodDescriptor(methodSubstitution);
-            parameters = new Class[signature.getParameterCount(false)];
-            for (int i = 0; i < parameters.length; i++) {
-                parameters[i] = resolveType(signature.getParameterType(i, null));
-            }
-        }
-        return parameters;
-    }
-
-    private static Member originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) {
-        Class<?> originalClass = classSubstitution.value();
-        if (originalClass == ClassSubstitution.class) {
-            originalClass = resolveType(classSubstitution.className(), classSubstitution.optional());
-            if (originalClass == null) {
-                // optional class was not found
-                return null;
-            }
-        }
-        try {
-            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.replacements/src/com/oracle/graal/replacements/ReplacementsProvider.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * 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.replacements;
-
-/**
- * Interface for service providers that install replacements into the compiler.
- */
-public interface ReplacementsProvider {
-
-    void installReplacements(ReplacementsInstaller installer);
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,8 +27,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -55,6 +53,13 @@
          * Determines if {@code method} should be inlined into {@code caller}.
          */
         boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
+
+        /**
+         * Determines if {@code method} should be inlined using its replacement graph.
+         * 
+         * @return true if the replacement graph should be used, false for normal inlining.
+         */
+        boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse);
     }
 
     /**
@@ -70,11 +75,9 @@
     public static class DefaultSnippetInliningPolicy implements SnippetInliningPolicy {
 
         private final MetaAccessProvider metaAccess;
-        private final BoxingMethodPool pool;
 
-        public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess, BoxingMethodPool pool) {
+        public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess) {
             this.metaAccess = metaAccess;
-            this.pool = pool;
         }
 
         @Override
@@ -89,16 +92,18 @@
                 return false;
             }
             if (metaAccess.lookupJavaType(Throwable.class).isAssignableFrom(method.getDeclaringClass())) {
-                if (method.getName().equals("<init>")) {
+                if (method.isConstructor()) {
                     return false;
                 }
             }
             if (method.getAnnotation(Word.Operation.class) != null) {
                 return false;
             }
-            if (pool.isSpecialMethod(method)) {
-                return false;
-            }
+            return true;
+        }
+
+        @Override
+        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
             return true;
         }
     }
@@ -116,20 +121,6 @@
     }
 
     /**
-     * Denotes a snippet parameter that will be bound during snippet template
-     * {@linkplain SnippetTemplate#instantiate instantiation}.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.PARAMETER)
-    public @interface Parameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
-    }
-
-    /**
      * Denotes a snippet parameter representing 0 or more arguments that will be bound during
      * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet
      * template creation, its value must be an array whose length specifies the number of arguments
@@ -143,11 +134,6 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface VarargsParameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
     }
 
     /**
@@ -157,61 +143,5 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface ConstantParameter {
-
-        /**
-         * The name of this constant.
-         */
-        String value();
-    }
-
-    /**
-     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
-     */
-    public static class Varargs {
-
-        private final Object args;
-        private final Class argType;
-        private final int length;
-        private final Stamp argStamp;
-
-        public static Varargs vargargs(Object array, Stamp argStamp) {
-            return new Varargs(array, argStamp);
-        }
-
-        public Varargs(Object array, Stamp argStamp) {
-            assert array != null;
-            this.argType = array.getClass().getComponentType();
-            this.argStamp = argStamp;
-            assert this.argType != null;
-            this.length = java.lang.reflect.Array.getLength(array);
-            this.args = array;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Varargs) {
-                Varargs other = (Varargs) obj;
-                return other.argType == argType && other.length == length;
-            }
-            return false;
-        }
-
-        public Object getArray() {
-            return args;
-        }
-
-        public Stamp getArgStamp() {
-            return argStamp;
-        }
-
-        @Override
-        public int hashCode() {
-            return argType.hashCode() ^ length;
-        }
-
-        @Override
-        public String toString() {
-            return argType.getName() + "[" + length + "]";
-        }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,7 +24,6 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.Map.Entry;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -34,14 +33,13 @@
 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.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.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.Snippet.Parameter;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.phases.*;
@@ -50,171 +48,274 @@
  * A snippet template is a graph created by parsing a snippet method and then specialized by binding
  * constants to the snippet's {@link ConstantParameter} parameters.
  * 
- * Snippet templates can be managed in a {@link Cache}.
+ * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}.
  */
 public class SnippetTemplate {
 
     /**
-     * A snippet template key encapsulates the method from which a snippet was built and the
-     * arguments used to specialize the snippet.
-     * 
-     * @see Cache
+     * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the
+     * method that needs to be computed only once. The {@link SnippetInfo} should be created once
+     * per snippet an then cached.
      */
-    public static class Key implements Iterable<Map.Entry<String, Object>> {
+    public static class SnippetInfo {
+
+        protected final ResolvedJavaMethod method;
+        protected final boolean[] constantParameters;
+        protected final boolean[] varargsParameters;
+
+        /**
+         * The parameter names, taken from the local variables table. Only used for assertion
+         * checking, so use only within an assert statement.
+         */
+        protected final String[] names;
+
+        protected SnippetInfo(ResolvedJavaMethod method) {
+            this.method = method;
 
-        public final ResolvedJavaMethod method;
-        private final HashMap<String, Object> map = new HashMap<>();
-        private int hash;
+            assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
+            int count = method.getSignature().getParameterCount(false);
+            constantParameters = new boolean[count];
+            varargsParameters = new boolean[count];
+            for (int i = 0; i < count; i++) {
+                constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method) != null;
+                varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method) != null;
+
+                assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" +
+                                VarargsParameter.class.getSimpleName();
+            }
 
-        public Key(ResolvedJavaMethod method) {
-            this.method = method;
-            this.hash = method.hashCode();
+            names = new String[count];
+            // Retrieve the names only when assertions are turned on.
+            assert initNames();
+        }
+
+        private boolean initNames() {
+            int slotIdx = 0;
+            for (int i = 0; i < names.length; i++) {
+                names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName();
+
+                Kind kind = method.getSignature().getParameterKind(i);
+                slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1;
+            }
+            return true;
         }
 
-        public Key add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            hash = hash ^ name.hashCode();
-            if (value != null) {
-                hash *= (value.hashCode() + 1);
-            }
+        public ResolvedJavaMethod getMethod() {
+            return method;
+        }
+
+        public int getParameterCount() {
+            return constantParameters.length;
+        }
+
+        public boolean isConstantParameter(int paramIdx) {
+            return constantParameters[paramIdx];
+        }
+
+        public boolean isVarargsParameter(int paramIdx) {
+            return varargsParameters[paramIdx];
+        }
+    }
+
+    /**
+     * Values that are bound to the snippet method parameters. The methods {@link #add},
+     * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the
+     * signature of the snippet method. The parameter name is passed to the add methods for
+     * assertion checking, i.e., to enforce that the order matches. Which method needs to be called
+     * depends on the annotation of the snippet method parameter:
+     * <ul>
+     * <li>Use {@link #add} for a parameter without an annotation. The value is bound when the
+     * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}.
+     * <li>Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value
+     * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}.
+     * <li>Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A
+     * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every
+     * distinct array length. The actual values are bound when the {@link SnippetTemplate} is
+     * {@link SnippetTemplate#instantiate instantiated}
+     * </ul>
+     */
+    public static class Arguments {
+
+        protected final SnippetInfo info;
+        protected final CacheKey cacheKey;
+        protected final Object[] values;
+
+        protected int nextParamIdx;
+
+        public Arguments(SnippetInfo info) {
+            this.info = info;
+            this.cacheKey = new CacheKey(info);
+            this.values = new Object[info.getParameterCount()];
+        }
+
+        public Arguments add(String name, Object value) {
+            assert check(name, false, false);
+            values[nextParamIdx] = value;
+            nextParamIdx++;
             return this;
         }
 
-        public int length() {
-            return map.size();
+        public Arguments addConst(String name, Object value) {
+            assert check(name, true, false);
+            values[nextParamIdx] = value;
+            cacheKey.setParam(nextParamIdx, value);
+            nextParamIdx++;
+            return this;
         }
 
-        public Object get(String name) {
-            return map.get(name);
+        public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) {
+            assert check(name, false, true);
+            Varargs varargs = new Varargs(componentType, argStamp, value);
+            values[nextParamIdx] = varargs;
+            // A separate template is necessary for every distinct array length
+            cacheKey.setParam(nextParamIdx, varargs.length);
+            nextParamIdx++;
+            return this;
+        }
+
+        private boolean check(String name, boolean constParam, boolean varargsParam) {
+            assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + "  " + this;
+            assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + "  " + this;
+            assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            return true;
         }
 
         @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
+        public String toString() {
+            StringBuilder result = new StringBuilder();
+            result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" [");
+            String sep = "";
+            for (int i = 0; i < info.getParameterCount(); i++) {
+                result.append(sep);
+                if (info.isConstantParameter(i)) {
+                    result.append("const ");
+                } else if (info.isVarargsParameter(i)) {
+                    result.append("varargs ");
+                }
+                result.append(info.names[i]).append(" = ").append(values[i]);
+                sep = ", ";
+            }
+            result.append(">");
+            return result.toString();
+        }
+    }
+
+    /**
+     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
+     */
+    static class Varargs {
+
+        protected final Class componentType;
+        protected final Stamp stamp;
+        protected final Object value;
+        protected final int length;
+
+        protected Varargs(Class componentType, Stamp stamp, Object value) {
+            this.componentType = componentType;
+            this.stamp = stamp;
+            this.value = value;
+            if (value instanceof List) {
+                this.length = ((List) value).size();
+            } else {
+                this.length = Array.getLength(value);
+            }
+        }
+    }
+
+    static class CacheKey {
+
+        private final ResolvedJavaMethod method;
+        private final Object[] values;
+        private int hash;
+
+        protected CacheKey(SnippetInfo info) {
+            this.method = info.method;
+            this.values = new Object[info.getParameterCount()];
+            this.hash = info.method.hashCode();
+        }
+
+        protected void setParam(int paramIdx, Object value) {
+            values[paramIdx] = value;
+            hash = (hash * 31) ^ (value == null ? 0 : value.hashCode());
         }
 
         @Override
         public boolean equals(Object obj) {
-            if (obj instanceof Key) {
-                Key other = (Key) obj;
-                return other.method == method && other.map.equals(map);
+            if (!(obj instanceof CacheKey)) {
+                return false;
+            }
+            CacheKey other = (CacheKey) obj;
+            if (method != other.method) {
+                return false;
             }
-            return false;
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] != null && !values[i].equals(other.values[i])) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         @Override
         public int hashCode() {
             return hash;
         }
-
-        @Override
-        public String toString() {
-            return MetaUtil.format("%h.%n", method) + map.toString();
-        }
-
-        public Set<String> names() {
-            return map.keySet();
-        }
     }
 
     /**
-     * Arguments used to instantiate a template.
+     * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s.
      */
-    public static class Arguments implements Iterable<Map.Entry<String, Object>> {
-
-        private final HashMap<String, Object> map = new HashMap<>();
+    public abstract static class AbstractTemplates {
 
-        public static Arguments arguments(String name, Object value) {
-            return new Arguments().add(name, value);
-        }
+        protected final MetaAccessProvider runtime;
+        protected final Replacements replacements;
+        protected final TargetDescription target;
+        private final ConcurrentHashMap<CacheKey, SnippetTemplate> templates;
 
-        public Arguments add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            return this;
-        }
-
-        public int length() {
-            return map.size();
+        protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+            this.runtime = runtime;
+            this.replacements = replacements;
+            this.target = target;
+            this.templates = new ConcurrentHashMap<>();
         }
 
-        @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
-        }
-
-        @Override
-        public String toString() {
-            return map.toString();
-        }
-    }
+        protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName) {
+            Method found = null;
+            for (Method method : declaringClass.getDeclaredMethods()) {
+                if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) {
+                    assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
+                    found = method;
+                }
+            }
+            assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
 
-    /**
-     * A collection of snippet templates accessed by a {@link Key} instance.
-     */
-    public static class Cache {
-
-        private final ConcurrentHashMap<SnippetTemplate.Key, SnippetTemplate> templates = new ConcurrentHashMap<>();
-        private final MetaAccessProvider runtime;
-        private final TargetDescription target;
-
-        public Cache(MetaAccessProvider runtime, TargetDescription target) {
-            this.runtime = runtime;
-            this.target = target;
+            return new SnippetInfo(runtime.lookupJavaMethod(found));
         }
 
         /**
          * Gets a template for a given key, creating it first if necessary.
          */
-        public SnippetTemplate get(final SnippetTemplate.Key key, final Assumptions assumptions) {
-            SnippetTemplate template = templates.get(key);
+        protected SnippetTemplate template(final Arguments args) {
+            SnippetTemplate template = templates.get(args.cacheKey);
             if (template == null) {
-                template = Debug.scope("SnippetSpecialization", key.method, new Callable<SnippetTemplate>() {
+                template = Debug.scope("SnippetSpecialization", args.info.method, new Callable<SnippetTemplate>() {
 
                     @Override
                     public SnippetTemplate call() throws Exception {
-                        return new SnippetTemplate(runtime, assumptions, target, key);
+                        return new SnippetTemplate(runtime, replacements, target, args);
                     }
                 });
-                // System.out.println(key + " -> " + template);
-                templates.put(key, template);
+                templates.put(args.cacheKey, template);
             }
             return template;
         }
     }
 
-    public abstract static class AbstractTemplates<T extends Snippets> {
-
-        protected final Cache cache;
-        protected final MetaAccessProvider runtime;
-        protected final Assumptions assumptions;
-        protected Class<?> snippetsClass;
-
-        public AbstractTemplates(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target, Class<T> snippetsClass) {
-            this.runtime = runtime;
-            this.assumptions = assumptions;
-            if (snippetsClass == null) {
-                assert this instanceof Snippets;
-                this.snippetsClass = getClass();
-            } else {
-                this.snippetsClass = snippetsClass;
-            }
-            this.cache = new Cache(runtime, target);
-        }
-
-        protected ResolvedJavaMethod snippet(String name, Class<?>... parameterTypes) {
-            try {
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes));
-                assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName();
-                return snippet;
-            } catch (NoSuchMethodException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-    }
-
     private static final Object UNUSED_PARAMETER = "DEAD PARAMETER";
+    private static final Object CONSTANT_PARAMETER = "CONSTANT";
 
     /**
      * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
@@ -231,28 +332,25 @@
     /**
      * Creates a snippet template.
      */
-    public SnippetTemplate(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target, SnippetTemplate.Key key) {
-        ResolvedJavaMethod method = key.method;
-        assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method;
+    protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) {
+        StructuredGraph snippetGraph = replacements.getSnippet(args.info.method);
+
+        ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
 
         // Copy snippet graph, replacing constant parameters with given arguments
-        StructuredGraph snippetGraph = (StructuredGraph) method.getCompilerStorage().get(Snippet.class);
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
-        IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
-        replacements.put(snippetGraph.start(), snippetCopy.start());
+        IdentityHashMap<Node, Node> nodeReplacements = new IdentityHashMap<>();
+        nodeReplacements.put(snippetGraph.start(), snippetCopy.start());
 
-        int parameterCount = signature.getParameterCount(false);
-        assert checkTemplate(runtime, key, parameterCount, method, signature);
+        assert checkTemplate(runtime, args, method, signature);
 
-        Parameter[] parameterAnnotations = new Parameter[parameterCount];
-        VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount];
+        int parameterCount = args.info.getParameterCount();
         ConstantNode[] placeholders = new ConstantNode[parameterCount];
+
         for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            if (c != null) {
-                String name = c.value();
-                Object arg = key.get(name);
+            if (args.info.isConstantParameter(i)) {
+                Object arg = args.values[i];
                 Kind kind = signature.getParameterKind(i);
                 Constant constantArg;
                 if (arg instanceof Constant) {
@@ -260,52 +358,45 @@
                 } else {
                     constantArg = Constant.forBoxed(kind, arg);
                 }
-                replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy));
-            } else {
-                VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-                if (vp != null) {
-                    String name = vp.value();
-                    Varargs varargs = (Varargs) key.get(name);
-                    Object array = varargs.getArray();
-                    ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
-                    replacements.put(snippetGraph.getLocal(i), placeholder);
-                    placeholders[i] = placeholder;
-                    varargsParameterAnnotations[i] = vp;
-                } else {
-                    parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-                }
+                nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy));
+            } else if (args.info.isVarargsParameter(i)) {
+                Varargs varargs = (Varargs) args.values[i];
+                Object array = Array.newInstance(varargs.componentType, varargs.length);
+                ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
+                nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
+                placeholders[i] = placeholder;
             }
         }
-        snippetCopy.addDuplicates(snippetGraph.getNodes(), replacements);
+        snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements);
 
         Debug.dump(snippetCopy, "Before specialization");
-        if (!replacements.isEmpty()) {
+        if (!nodeReplacements.isEmpty()) {
             // Do deferred intrinsification of node intrinsics
-            new NodeIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy);
+            new NodeIntrinsificationPhase(runtime).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase(runtime, assumptions, 0, null).apply(snippetCopy);
+            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
         }
         assert NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
         // Gather the template parameters
-        parameters = new HashMap<>();
+        parameters = new Object[parameterCount];
         for (int i = 0; i < parameterCount; i++) {
-            VarargsParameter vp = varargsParameterAnnotations[i];
-            if (vp != null) {
+            if (args.info.isConstantParameter(i)) {
+                parameters[i] = CONSTANT_PARAMETER;
+            } else if (args.info.isVarargsParameter(i)) {
                 assert snippetCopy.getLocal(i) == null;
-                Varargs varargs = (Varargs) key.get(vp.value());
-                Object array = varargs.getArray();
-                int length = Array.getLength(array);
+                Varargs varargs = (Varargs) args.values[i];
+                int length = varargs.length;
                 LocalNode[] locals = new LocalNode[length];
-                Stamp stamp = varargs.getArgStamp();
+                Stamp stamp = varargs.stamp;
                 for (int j = 0; j < length; j++) {
                     assert (parameterCount & 0xFFFF) == parameterCount;
                     int idx = i << 16 | j;
                     LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp));
                     locals[j] = local;
                 }
-                parameters.put(vp.value(), locals);
+                parameters[i] = locals;
 
                 ConstantNode placeholder = placeholders[i];
                 assert placeholder != null;
@@ -319,15 +410,12 @@
                     }
                 }
             } else {
-                Parameter p = parameterAnnotations[i];
-                if (p != null) {
-                    LocalNode local = snippetCopy.getLocal(i);
-                    if (local == null) {
-                        // Parameter value was eliminated
-                        parameters.put(p.value(), UNUSED_PARAMETER);
-                    } else {
-                        parameters.put(p.value(), local);
-                    }
+                LocalNode local = snippetCopy.getLocal(i);
+                if (local == null) {
+                    // Parameter value was eliminated
+                    parameters[i] = UNUSED_PARAMETER;
+                } else {
+                    parameters[i] = local;
                 }
             }
         }
@@ -344,7 +432,7 @@
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
                     LoopTransformations.fullUnroll(loop, runtime, null);
-                    new CanonicalizerPhase(runtime, assumptions, mark, null).apply(snippetCopy);
+                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -426,11 +514,11 @@
         return true;
     }
 
-    private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
-        Object arg = varargs.getArray();
+    private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
         ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
         assert type.isArray() : "varargs parameter must be an array type";
-        assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg;
+        assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " +
+                        varargs.componentType;
         return true;
     }
 
@@ -445,7 +533,7 @@
      * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the
      * value is identical to the key.
      */
-    private final Map<String, Object> parameters;
+    private final Object[] parameters;
 
     /**
      * The return node (if any) of the snippet.
@@ -473,33 +561,33 @@
      * 
      * @return the map that will be used to bind arguments to parameters when inlining this template
      */
-    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) {
+    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) {
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
-        assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")";
-        for (Map.Entry<String, Object> e : args) {
-            String name = e.getKey();
-            Object parameter = parameters.get(name);
-            assert parameter != null : this + " has no parameter named " + name;
-            Object argument = e.getValue();
+        assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")";
+        for (int i = 0; i < parameters.length; i++) {
+            Object parameter = parameters[i];
+            assert parameter != null : this + " has no parameter named " + args.info.names[i];
+            Object argument = args.values[i];
             if (parameter instanceof LocalNode) {
                 if (argument instanceof ValueNode) {
                     replacements.put((LocalNode) parameter, (ValueNode) argument);
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
-                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name;
-                    Constant constant = Constant.forBoxed(kind, argument);
+                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i];
+                    Constant constant = forBoxed(argument, kind);
                     replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
             } else if (parameter instanceof LocalNode[]) {
                 LocalNode[] locals = (LocalNode[]) parameter;
+                Varargs varargs = (Varargs) argument;
                 int length = locals.length;
                 List list = null;
                 Object array = null;
-                if (argument instanceof List) {
-                    list = (List) argument;
+                if (varargs.value instanceof List) {
+                    list = (List) varargs.value;
                     assert list.size() == length : length + " != " + list.size();
                 } else {
-                    array = argument;
+                    array = varargs.value;
                     assert array != null && array.getClass().isArray();
                     assert Array.getLength(array) == length : length + " != " + Array.getLength(array);
                 }
@@ -511,19 +599,45 @@
                     if (value instanceof ValueNode) {
                         replacements.put(local, (ValueNode) value);
                     } else {
-                        Constant constant = Constant.forBoxed(local.kind(), value);
+                        Constant constant = forBoxed(value, local.kind());
                         ConstantNode element = ConstantNode.forConstant(constant, runtime, replaceeGraph);
                         replacements.put(local, element);
                     }
                 }
             } else {
-                assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter;
+                assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter;
             }
         }
         return replacements;
     }
 
     /**
+     * Converts a Java boxed value to a {@link Constant} of the right kind. This adjusts for the
+     * limitation that a {@link Local}'s kind is a {@linkplain Kind#getStackKind() stack kind} and
+     * so cannot be used for re-boxing primitives smaller than an int.
+     * 
+     * @param argument a Java boxed value
+     * @param localKind the kind of the {@link Local} to which {@code argument} will be bound
+     */
+    protected Constant forBoxed(Object argument, Kind localKind) {
+        assert localKind == localKind.getStackKind();
+        if (localKind == Kind.Int && !(argument instanceof Integer)) {
+            if (argument instanceof Boolean) {
+                return Constant.forBoxed(Kind.Boolean, argument);
+            }
+            if (argument instanceof Byte) {
+                return Constant.forBoxed(Kind.Byte, argument);
+            }
+            if (argument instanceof Short) {
+                return Constant.forBoxed(Kind.Short, argument);
+            }
+            assert argument instanceof Character;
+            return Constant.forBoxed(Kind.Char, argument);
+        }
+        return Constant.forBoxed(localKind, argument);
+    }
+
+    /**
      * Logic for replacing a snippet-lowered node at its usages with the return value of the
      * snippet. An alternative to the {@linkplain SnippetTemplate#DEFAULT_REPLACER default}
      * replacement logic can be used to handle mismatches between the stamp of the node being
@@ -558,7 +672,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, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) {
+    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -634,7 +748,7 @@
      * @param replacer object that replaces the usages of {@code replacee}
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      */
-    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) {
+    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -693,13 +807,17 @@
     public String toString() {
         StringBuilder buf = new StringBuilder(snippet.toString()).append('(');
         String sep = "";
-        for (Map.Entry<String, Object> e : parameters.entrySet()) {
-            String name = e.getKey();
-            Object value = e.getValue();
+        for (int i = 0; i < parameters.length; i++) {
+            String name = "[" + i + "]";
+            Object value = parameters[i];
             buf.append(sep);
             sep = ", ";
-            if (value == UNUSED_PARAMETER) {
+            if (value == null) {
+                buf.append("<null> ").append(name);
+            } else if (value == UNUSED_PARAMETER) {
                 buf.append("<unused> ").append(name);
+            } else if (value == CONSTANT_PARAMETER) {
+                buf.append("<constant> ").append(name);
             } else if (value instanceof LocalNode) {
                 LocalNode local = (LocalNode) value;
                 buf.append(local.kind().getJavaName()).append(' ').append(name);
@@ -712,42 +830,18 @@
         return buf.append(')').toString();
     }
 
-    private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) {
-        Set<String> expected = new HashSet<>();
-        for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-            Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-            if (c != null) {
-                assert vp == null && p == null;
-                String name = c.value();
-                expected.add(name);
+    private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) {
+        for (int i = 0; i < args.info.getParameterCount(); i++) {
+            if (args.info.isConstantParameter(i)) {
                 Kind kind = signature.getParameterKind(i);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind);
-            } else if (vp != null) {
-                assert p == null;
-                String name = vp.value();
-                expected.add(name);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert key.get(name) instanceof Varargs;
-                Varargs varargs = (Varargs) key.get(name);
-                assert checkVarargs(method, signature, i, name, varargs);
-            } else {
-                assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" +
-                                VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName();
+                assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind);
+
+            } else if (args.info.isVarargsParameter(i)) {
+                assert args.values[i] instanceof Varargs;
+                Varargs varargs = (Varargs) args.values[i];
+                assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs);
             }
         }
-        if (!key.names().containsAll(expected)) {
-            expected.removeAll(key.names());
-            assert false : expected + " missing from key " + key;
-        }
-        if (!expected.containsAll(key.names())) {
-            Set<String> namesCopy = new HashSet<>(key.names());
-            namesCopy.removeAll(expected);
-            assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " +
-                            MetaUtil.format("%H.%n(%p)", method);
-        }
         return true;
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
@@ -63,7 +64,7 @@
     public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) this.graph();
         IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1);
-        WriteNode write = graph.add(new WriteNode(object, value, location));
+        WriteNode write = graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE));
         graph.replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -47,7 +47,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, false));
+        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, null));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -50,7 +50,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, false);
+        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, null);
     }
 
     /*
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -41,7 +41,7 @@
     private final JavaType returnType;
 
     protected MacroNode(Invoke invoke) {
-        super(invoke.node().stamp(), invoke.stateAfter());
+        super(invoke.asNode().stamp(), invoke.stateAfter());
         this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments());
         this.bci = invoke.bci();
         this.targetMethod = invoke.methodCallTarget().targetMethod();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -107,6 +107,8 @@
                     return ConstantNode.forDouble(Math.cos(value), graph());
                 case TAN:
                     return ConstantNode.forDouble(Math.tan(value), graph());
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
         return this;
--- a/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Mon Apr 15 08:51:19 2013 +0200
@@ -29,6 +29,7 @@
 import javax.lang.model.*;
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+import javax.lang.model.util.*;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.*;
 
@@ -81,27 +82,57 @@
         return true;
     }
 
+    private void processElement(TypeElement serviceProvider) {
+        ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class);
+        if (annotation != null) {
+            try {
+                annotation.value();
+            } catch (MirroredTypeException ex) {
+                TypeMirror serviceInterface = ex.getTypeMirror();
+                if (verifyAnnotation(serviceInterface, serviceProvider)) {
+                    String interfaceName = ex.getTypeMirror().toString();
+                    addProvider(interfaceName, serviceProvider);
+                }
+            }
+        }
+    }
+
+    private void processOldElements() {
+        Filer filer = processingEnv.getFiler();
+        Elements elements = processingEnv.getElementUtils();
+        for (String key : serviceMap.keySet()) {
+            String filename = "META-INF/services/" + key;
+            try {
+                FileObject servicesFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "", filename);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(servicesFile.openInputStream(), "UTF-8"));
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    TypeElement serviceProvider = elements.getTypeElement(line);
+                    if (serviceProvider != null) {
+                        processElement(serviceProvider);
+                    }
+                }
+                reader.close();
+                servicesFile.delete();
+            } catch (IOException e) {
+                // old services file not found: do nothing
+            }
+        }
+    }
+
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (roundEnv.processingOver()) {
+            processOldElements();
             generateServicesFiles();
             return true;
         }
 
         for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
             assert element.getKind().isClass();
-            ServiceProvider annotation = element.getAnnotation(ServiceProvider.class);
-            try {
-                annotation.value();
-            } catch (MirroredTypeException ex) {
-                TypeMirror serviceInterface = ex.getTypeMirror();
-                TypeElement serviceProvider = (TypeElement) element;
-                if (verifyAnnotation(serviceInterface, serviceProvider)) {
-                    String interfaceName = ex.getTypeMirror().toString();
-                    addProvider(interfaceName, serviceProvider);
-                }
-            }
+            processElement((TypeElement) element);
         }
+
         return true;
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -30,9 +30,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
-/**
- * The {@code StoreFieldNode} represents a write to a static or instance field.
- */
 @NodeInfo(nameTemplate = "MaterializeStore#{p#target/s}")
 public final class CyclicMaterializeStoreNode extends FixedWithNextNode implements Lowerable, Virtualizable {
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -44,10 +43,18 @@
         this.values = new NodeInputList<>(this, virtualObject.entryCount());
     }
 
-    public NodeInputList<ValueNode> values() {
+    public NodeInputList<ValueNode> getValues() {
         return values;
     }
 
+    public VirtualObjectNode getVirtualObject() {
+        return virtualObject;
+    }
+
+    public int getLockCount() {
+        return lockCount;
+    }
+
     @Override
     public ValueNode length() {
         assert virtualObject.type().isArray();
@@ -73,38 +80,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        StructuredGraph graph = (StructuredGraph) graph();
-
-        boolean defaultValuesOnly = isDefault();
-
-        if (virtualObject instanceof VirtualInstanceNode) {
-            VirtualInstanceNode virtual = (VirtualInstanceNode) virtualObject;
-
-            NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), defaultValuesOnly, lockCount > 0));
-            this.replaceAtUsages(newInstance);
-            graph.addBeforeFixed(this, newInstance);
-
-            if (!defaultValuesOnly) {
-                for (int i = 0; i < virtual.entryCount(); i++) {
-                    graph.addBeforeFixed(this, graph.add(new StoreFieldNode(newInstance, virtual.field(i), values.get(i))));
-                }
-            }
-        } else {
-            assert virtualObject instanceof VirtualArrayNode;
-            VirtualArrayNode virtual = (VirtualArrayNode) virtualObject;
-
-            ResolvedJavaType element = virtual.componentType();
-            NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0));
-            this.replaceAtUsages(newArray);
-            graph.addBeforeFixed(this, newArray);
-
-            if (!defaultValuesOnly) {
-                for (int i = 0; i < virtual.entryCount(); i++) {
-                    graph.addBeforeFixed(this, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i))));
-                }
-            }
-        }
-        graph.removeFixed(this);
+        virtualObject.materializeAt(this, values, isDefault(), lockCount);
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Mon Apr 15 08:51:19 2013 +0200
@@ -40,7 +40,7 @@
     private final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
     private final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
     private final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
-    private final HashMap<ReadCacheEntry, ValueNode> readCache;
+    final HashMap<ReadCacheEntry, ValueNode> readCache;
 
     static class ReadCacheEntry {
 
@@ -167,8 +167,6 @@
 
         ValueNode[] fieldState = obj.getEntries();
 
-        // some entries are not default constants - do the materialization
-        virtual.materializeAt(fixed);
         MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount());
         ValueNode[] values = new ValueNode[obj.getEntries().length];
         materialize.setProbability(fixed.probability());
@@ -249,70 +247,13 @@
         return objectStates.values();
     }
 
-    public Iterable<VirtualObjectNode> getVirtualObjects() {
+    public Collection<VirtualObjectNode> getVirtualObjects() {
         return objectAliases.values();
     }
 
     @Override
     public String toString() {
-        return objectStates.toString();
-    }
-
-    public void mergeReadCache(List<BlockState> states, MergeNode merge, GraphEffectList effects) {
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
-            ReadCacheEntry key = entry.getKey();
-            ValueNode value = entry.getValue();
-            boolean phi = false;
-            for (int i = 1; i < states.size(); i++) {
-                ValueNode otherValue = states.get(i).readCache.get(key);
-                if (otherValue == null) {
-                    value = null;
-                    phi = false;
-                    break;
-                }
-                if (!phi && otherValue != value) {
-                    phi = true;
-                }
-            }
-            if (phi) {
-                PhiNode phiNode = new PhiNode(value.kind(), merge);
-                effects.addFloatingNode(phiNode);
-                for (int i = 0; i < states.size(); i++) {
-                    effects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
-                }
-                readCache.put(key, phiNode);
-            } else if (value != null) {
-                readCache.put(key, value);
-            }
-        }
-        for (PhiNode phi : merge.phis()) {
-            if (phi.kind() == Kind.Object) {
-                for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
-                    if (entry.getKey().object == phi.valueAt(0)) {
-                        mergeReadCachePhi(phi, entry.getKey().identity, states, merge, effects);
-                    }
-                }
-
-            }
-        }
-    }
-
-    private void mergeReadCachePhi(PhiNode phi, Object identity, List<BlockState> states, MergeNode merge, GraphEffectList effects) {
-        ValueNode[] values = new ValueNode[phi.valueCount()];
-        for (int i = 0; i < phi.valueCount(); i++) {
-            ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
-            if (value == null) {
-                return;
-            }
-            values[i] = value;
-        }
-
-        PhiNode phiNode = new PhiNode(values[0].kind(), merge);
-        effects.addFloatingNode(phiNode);
-        for (int i = 0; i < values.length; i++) {
-            effects.addPhiInput(phiNode, values[i]);
-        }
-        readCache.put(new ReadCacheEntry(identity, phi), phiNode);
+        return objectStates + " " + readCache;
     }
 
     public static BlockState meetAliases(List<BlockState> states) {
@@ -349,4 +290,38 @@
         return readCache;
     }
 
+    public boolean equivalentTo(BlockState other) {
+        if (this == other) {
+            return true;
+        }
+        boolean objectAliasesEqual = compareMaps(objectAliases, other.objectAliases);
+        boolean objectStatesEqual = compareMaps(objectStates, other.objectStates);
+        boolean readCacheEqual = compareMapsNoSize(readCache, other.readCache);
+        boolean scalarAliasesEqual = scalarAliases.equals(other.scalarAliases);
+        return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual;
+    }
+
+    private static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    private static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
+        if (left == right) {
+            return true;
+        }
+        for (Map.Entry<K, V> entry : right.entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
+            assert value != null;
+            V otherValue = left.get(key);
+            if (otherValue != value && !value.equals(otherValue)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Mon Apr 15 08:51:19 2013 +0200
@@ -73,48 +73,47 @@
         public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
     }
 
-    private Effect[] effects = new Effect[16];
-    private int[] level = new int[16];
+    private static final Effect[] EMPTY_ARRAY = new Effect[0];
+
+    private Effect[] effects = EMPTY_ARRAY;
     private int size;
-    private int currentLevel;
+
+    private void enlarge(int elements) {
+        int length = effects.length;
+        if (size + elements > length) {
+            while (size + elements > length) {
+                length = Math.max(length * 2, 4);
+            }
+            effects = Arrays.copyOf(effects, length);
+        }
+    }
 
     public void add(Effect effect) {
-        if (effects.length == size) {
-            effects = Arrays.copyOf(effects, effects.length * 2);
-            level = Arrays.copyOf(level, effects.length);
-        }
-        level[size] = currentLevel;
+        assert effect != null;
+        enlarge(1);
         effects[size++] = effect;
     }
 
     public void addAll(Collection<? extends Effect> list) {
-        int length = effects.length;
-        if (size + list.size() > length) {
-            while (size + list.size() > length) {
-                length *= 2;
-            }
-            effects = Arrays.copyOf(effects, length);
-            level = Arrays.copyOf(level, effects.length);
-        }
+        enlarge(list.size());
         for (Effect effect : list) {
-            level[size] = currentLevel;
+            assert effect != null;
             effects[size++] = effect;
         }
     }
 
     public void addAll(EffectList list) {
-        int length = effects.length;
-        if (size + list.size > length) {
-            while (size + list.size > length) {
-                length *= 2;
-            }
-            effects = Arrays.copyOf(effects, length);
-            level = Arrays.copyOf(level, effects.length);
-        }
-        for (Effect effect : list) {
-            level[size] = currentLevel;
-            effects[size++] = effect;
-        }
+        enlarge(list.size);
+        System.arraycopy(list.effects, 0, effects, size, list.size);
+        size += list.size;
+    }
+
+    public void insertAll(EffectList list, int position) {
+        assert position >= 0 && position <= size;
+        enlarge(list.size);
+        System.arraycopy(effects, position, effects, position + list.size, size - position);
+        System.arraycopy(list.effects, 0, effects, position, list.size);
+        size += list.size;
     }
 
     public int checkpoint() {
@@ -154,14 +153,6 @@
         };
     }
 
-    public void incLevel() {
-        currentLevel++;
-    }
-
-    public void decLevel() {
-        currentLevel--;
-    }
-
     public Effect get(int index) {
         if (index >= size) {
             throw new IndexOutOfBoundsException();
@@ -169,13 +160,6 @@
         return effects[index];
     }
 
-    public int levelAt(int index) {
-        if (index >= size) {
-            throw new IndexOutOfBoundsException();
-        }
-        return level[index];
-    }
-
     public void clear() {
         size = 0;
     }
@@ -190,9 +174,6 @@
         for (int i = 0; i < size(); i++) {
             Effect effect = get(i);
             if (effect.isVisible()) {
-                for (int i2 = 0; i2 < levelAt(i); i2++) {
-                    str.append("    ");
-                }
                 str.append(effect).append('\n');
             }
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Apr 15 08:51:19 2013 +0200
@@ -104,17 +104,17 @@
      * 
      * @param node The floating node to be added.
      */
-    public void addFloatingNode(final ValueNode node) {
+    public void addFloatingNode(final ValueNode node, final String cause) {
         add(new Effect() {
 
             @Override
             public String name() {
-                return "addFloatingNode";
+                return "addFloatingNode " + cause;
             }
 
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted();
+                assert !node.isAlive() && !node.isDeleted() : node + " " + cause;
                 graph.add(node);
             }
         });
@@ -142,7 +142,7 @@
                 graph.addBeforeFixed(position, graph.add(node));
                 node.setProbability(position.probability());
                 for (int i = 0; i < values.length; i++) {
-                    node.values().set(i, values[i]);
+                    node.getValues().set(i, values[i]);
                 }
             }
         });
@@ -164,7 +164,7 @@
 
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive();
+                assert node.isAlive() && value.isAlive() : node + " " + value;
                 node.addInput(value);
             }
         });
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,26 +25,24 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class IterativeInliningPhase extends Phase {
+public class IterativeInliningPhase extends BasePhase<HighTierContext> {
 
     private final PhasePlan plan;
 
-    private final GraalCodeCacheProvider runtime;
-    private final Assumptions assumptions;
+    private final Replacements replacements;
     private final GraphCache cache;
     private final OptimisticOptimizations optimisticOpts;
     private final boolean readElimination;
 
-    public IterativeInliningPhase(GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
+    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
+        this.replacements = replacements;
         this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
@@ -58,12 +56,12 @@
     }
 
     @Override
-    protected void run(final StructuredGraph graph) {
-        runIterations(graph, true);
-        runIterations(graph, false);
+    protected void run(final StructuredGraph graph, final HighTierContext context) {
+        runIterations(graph, true, context);
+        runIterations(graph, false, context);
     }
 
-    private void runIterations(final StructuredGraph graph, final boolean simple) {
+    private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) {
         Boolean continueIteration = true;
         for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
             continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
@@ -71,13 +69,13 @@
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(runtime, assumptions, false, readElimination);
-                    ea.apply(graph);
-                    progress |= ea.hasChanged();
+                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination);
+                    boolean eaResult = ea.runAnalysis(graph, context);
+                    progress |= eaResult;
 
                     Map<Invoke, Double> hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null;
 
-                    InliningPhase inlining = new InliningPhase(runtime, hints, assumptions, cache, plan, optimisticOpts);
+                    InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts);
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
                     inlining.apply(graph);
                     progress |= inlining.getInliningCount() > 0;
@@ -85,8 +83,8 @@
                     new DeadCodeEliminationPhase().apply(graph);
 
                     if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(runtime, assumptions).apply(graph);
-                        new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
+                        new CanonicalizerPhase().apply(graph, context);
+                        new IterativeConditionalEliminationPhase(context.getRuntime(), context.getAssumptions()).apply(graph);
                     }
 
                     return progress;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
@@ -144,4 +146,48 @@
 
         return str.append('}').toString();
     }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Arrays.hashCode(entries);
+        result = prime * result + lockCount;
+        result = prime * result + ((materializedValue == null) ? 0 : materializedValue.hashCode());
+        result = prime * result + ((state == null) ? 0 : state.hashCode());
+        result = prime * result + ((virtual == null) ? 0 : virtual.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        ObjectState other = (ObjectState) obj;
+        if (!Arrays.equals(entries, other.entries)) {
+            return false;
+        }
+        if (lockCount != other.lockCount) {
+            return false;
+        }
+        if (materializedValue == null) {
+            if (other.materializedValue != null) {
+                return false;
+            }
+        } else if (!materializedValue.equals(other.materializedValue)) {
+            return false;
+        }
+        if (state != other.state) {
+            return false;
+        }
+        assert virtual != null && other.virtual != null;
+        if (!virtual.equals(other.virtual)) {
+            return false;
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,12 +25,10 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-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.debug.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
@@ -38,34 +36,25 @@
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
-import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
-public class PartialEscapeAnalysisPhase extends Phase {
+public class PartialEscapeAnalysisPhase extends BasePhase<HighTierContext> {
 
-    private final MetaAccessProvider runtime;
-    private final Assumptions assumptions;
-    private CustomCanonicalizer customCanonicalizer;
+    private final CustomCanonicalizer customCanonicalizer;
     private final boolean iterative;
     private final boolean readElimination;
 
-    private boolean changed;
+    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) {
+        this(null, iterative, readElimination);
+    }
 
-    public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative, boolean readElimination) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
+    public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) {
+        this.customCanonicalizer = customCanonicalizer;
         this.iterative = iterative;
         this.readElimination = readElimination;
     }
 
-    public boolean hasChanged() {
-        return changed;
-    }
-
-    public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
-        this.customCanonicalizer = customCanonicalizer;
-    }
-
     public static final void trace(String format, Object... obj) {
         if (GraalOptions.TraceEscapeAnalysis) {
             Debug.log(format, obj);
@@ -73,9 +62,13 @@
     }
 
     @Override
-    protected void run(final StructuredGraph graph) {
+    protected void run(StructuredGraph graph, HighTierContext context) {
+        runAnalysis(graph, context);
+    }
+
+    public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) {
         if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) {
-            return;
+            return false;
         }
 
         if (!readElimination) {
@@ -87,33 +80,29 @@
                 }
             }
             if (!analyzableNodes) {
-                return;
+                return false;
             }
         }
 
-        Boolean continueIteration = true;
+        boolean continueIteration = true;
+        boolean changed = false;
         for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
-            continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
+            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
 
                 @Override
                 public Boolean call() {
 
                     SchedulePhase schedule = new SchedulePhase();
                     schedule.apply(graph, false);
-                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions);
+                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, context.getRuntime(), context.getAssumptions());
                     ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null);
 
                     if (!closure.hasChanged()) {
                         return false;
                     }
-                    changed = true;
 
                     // apply the effects collected during the escape analysis iteration
-                    ArrayList<Node> obsoleteNodes = new ArrayList<>();
-                    for (Effect effect : closure.getEffects()) {
-                        effect.apply(graph, obsoleteNodes);
-                    }
-                    trace("%s\n", closure.getEffects());
+                    List<Node> obsoleteNodes = closure.applyEffects(graph);
 
                     Debug.dump(graph, "after PartialEscapeAnalysis iteration");
                     assert noObsoleteNodes(graph, obsoleteNodes);
@@ -121,21 +110,17 @@
                     new DeadCodeEliminationPhase().apply(graph);
 
                     if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph);
+                        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph);
                     }
 
-                    return iterative;
+                    return true;
                 }
             });
+            continueIteration = currentChanged && iterative;
+            changed |= currentChanged;
         }
 
-        if (DynamicCounterNode.enabled && readElimination) {
-            for (Node node : graph.getNodes()) {
-                if (node instanceof LoadFieldNode) {
-                    DynamicCounterNode.addCounterBefore("load non-elim", 1, false, (FixedNode) node);
-                }
-            }
-        }
+        return changed;
     }
 
     private static boolean matches(StructuredGraph graph, String filter) {
@@ -146,7 +131,7 @@
         return true;
     }
 
-    static boolean noObsoleteNodes(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+    static boolean noObsoleteNodes(StructuredGraph graph, List<Node> obsoleteNodes) {
         // helper code that determines the paths that keep obsolete nodes alive:
 
         NodeFlood flood = graph.createNodeFlood();
@@ -196,14 +181,13 @@
                 }
             }
         }
-
         boolean success = true;
         for (Node node : obsoleteNodes) {
             if (flood.isMarked(node)) {
-                System.out.print("offending node path:");
+                TTY.print("offending node path:");
                 Node current = node;
                 while (current != null) {
-                    System.out.println(current.toString());
+                    TTY.println(current.toString());
                     current = path.get(current);
                     if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) {
                         break;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Apr 15 08:51:19 2013 +0200
@@ -46,6 +46,7 @@
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry;
+import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
 class PartialEscapeClosure extends BlockIteratorClosure<BlockState> {
 
@@ -65,7 +66,8 @@
     private final NodeBitMap usages;
     private final SchedulePhase schedule;
 
-    private final GraphEffectList effects = new GraphEffectList();
+    private final BlockMap<GraphEffectList> blockEffects;
+    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
 
     private final VirtualizerToolImpl tool;
 
@@ -76,19 +78,57 @@
     public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
         this.schedule = schedule;
-        tool = new VirtualizerToolImpl(effects, usages, metaAccess, assumptions);
+        this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
+        this.blockEffects = new BlockMap<>(schedule.getCFG());
+        for (Block block : schedule.getCFG().getBlocks()) {
+            blockEffects.put(block, new GraphEffectList());
+        }
     }
 
     public boolean hasChanged() {
         return changed;
     }
 
-    public GraphEffectList getEffects() {
-        return effects;
-    }
+    public List<Node> applyEffects(final StructuredGraph graph) {
+        final ArrayList<Node> obsoleteNodes = new ArrayList<>();
+        BlockIteratorClosure<Object> closure = new BlockIteratorClosure<Object>() {
+
+            private void apply(GraphEffectList effects, Object context) {
+                if (!effects.isEmpty()) {
+                    Debug.log(" ==== effects for %s", context);
+                    for (Effect effect : effects) {
+                        effect.apply(graph, obsoleteNodes);
+                        if (effect.isVisible()) {
+                            Debug.log("    %s", effect);
+                        }
+                    }
+                }
+            }
 
-    public int getNewVirtualObjectCount() {
-        return tool.getNewVirtualObjectCount();
+            @Override
+            protected void processBlock(Block block, Object currentState) {
+                apply(blockEffects.get(block), block);
+            }
+
+            @Override
+            protected Object merge(Block merge, List<Object> states) {
+                return new Object();
+            }
+
+            @Override
+            protected Object cloneState(Object oldState) {
+                return oldState;
+            }
+
+            @Override
+            protected List<Object> processLoop(Loop loop, Object initialState) {
+                LoopInfo<Object> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
+                apply(loopMergeEffects.get(loop), loop);
+                return info.exitStates;
+            }
+        };
+        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new Object(), null);
+        return obsoleteNodes;
     }
 
     public Map<Invoke, Double> getHints() {
@@ -97,6 +137,9 @@
 
     @Override
     protected void processBlock(Block block, BlockState state) {
+        GraphEffectList effects = blockEffects.get(block);
+        tool.setEffects(effects);
+
         trace("\nBlock: %s (", block);
         List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block);
 
@@ -105,7 +148,7 @@
             boolean deleted;
             if (usages.isMarked(node) || node instanceof VirtualizableAllocation) {
                 trace("[[%s]] ", node);
-                deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state);
+                deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state, effects);
             } else {
                 trace("%s ", node);
                 deleted = false;
@@ -119,7 +162,6 @@
                         state.killReadCache(store.field());
 
                         if (cachedValue == store.value()) {
-                            effects.addCounterBefore("store elim", 1, false, lastFixedNode.next());
                             effects.deleteFixedNode(store);
                             changed = true;
                         } else {
@@ -130,7 +172,6 @@
                         ValueNode cachedValue = state.getReadCache(load.object(), load.field());
                         if (cachedValue != null) {
                             METRIC_LOADFIELD_ELIMINATED.increment();
-                            effects.addCounterBefore("load elim", 1, false, lastFixedNode.next());
                             effects.replaceAtUsages(load, cachedValue);
                             state.addScalarAlias(load, cachedValue);
                             changed = true;
@@ -154,7 +195,7 @@
         trace(")\n    end state: %s\n", state);
     }
 
-    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) {
+    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state, final GraphEffectList effects) {
         tool.reset(state, node);
         if (node instanceof Virtualizable) {
             ((Virtualizable) node).virtualize(tool);
@@ -250,13 +291,13 @@
                     hints.put(invoke, 5d);
                 }
                 trace("replacing input %s at %s: %s", input, node, obj);
-                replaceWithMaterialized(input, node, insertBefore, state, obj, METRIC_MATERIALIZATIONS_UNHANDLED);
+                replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
             }
         }
         return false;
     }
 
-    private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, DebugMetric metric) {
+    private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
             metric.increment();
@@ -267,34 +308,204 @@
         assert !obj.isVirtual();
     }
 
-    private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, DebugMetric metric) {
-        ensureMaterialized(state, obj, materializeBefore, metric);
+    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
+        ensureMaterialized(state, obj, materializeBefore, effects, metric);
         effects.replaceFirstInput(usage, value, obj.getMaterializedValue());
     }
 
     @Override
-    protected BlockState merge(MergeNode merge, List<BlockState> states) {
-        BlockState newState = BlockState.meetAliases(states);
+    protected BlockState merge(Block merge, List<BlockState> states) {
+        assert blockEffects.get(merge).isEmpty();
+        MergeProcessor processor = new MergeProcessor(merge, usages, blockEffects);
+        processor.merge(states);
+        blockEffects.get(merge).addAll(processor.mergeEffects);
+        blockEffects.get(merge).addAll(processor.afterMergeEffects);
+        return processor.newState;
+
+    }
+
+    @Override
+    protected BlockState cloneState(BlockState oldState) {
+        return oldState.cloneState();
+    }
+
+    @Override
+    protected List<BlockState> processLoop(Loop loop, BlockState initialState) {
+        BlockState loopEntryState = initialState;
+        BlockState lastMergedState = initialState;
+        MergeProcessor mergeProcessor = new MergeProcessor(loop.header, usages, blockEffects);
+        for (int iteration = 0; iteration < 10; iteration++) {
+            LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, lastMergedState.cloneState());
+
+            List<BlockState> states = new ArrayList<>();
+            states.add(initialState);
+            states.addAll(info.endStates);
+            mergeProcessor.merge(states);
 
-        // Iterative processing:
-        // Merging the materialized/virtual state of virtual objects can lead to new
-        // materializations, which can
-        // lead to new materializations because of phis, and so on.
+            Debug.log("================== %s", loop.header);
+            Debug.log("%s", mergeProcessor.newState);
+            Debug.log("===== vs.");
+            Debug.log("%s", lastMergedState);
+
+            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
+                blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0);
+                loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
+
+                assert info.exitStates.size() == loop.exits.size();
+                for (int i = 0; i < loop.exits.size(); i++) {
+                    BlockState exitState = info.exitStates.get(i);
+                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
+                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i)));
+                }
+
+                return info.exitStates;
+            } else {
+                lastMergedState = mergeProcessor.newState;
+                for (Block block : loop.blocks) {
+                    blockEffects.get(block).clear();
+                }
+            }
+        }
+        throw new GraalInternalError("too many iterations at %s", loop);
+    }
+
+    private static void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState, GraphEffectList effects) {
+        HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
 
-        boolean materialized;
-        do {
-            materialized = false;
-            // use a hash set to make the values distinct...
-            for (VirtualObjectNode object : newState.getVirtualObjects()) {
-                ObjectState resultState = newState.getObjectStateOptional(object);
-                if (resultState == null || resultState.isVirtual()) {
+        for (ProxyNode proxy : exitNode.proxies()) {
+            ObjectState obj = exitState.getObjectState(proxy.value());
+            if (obj != null) {
+                proxies.put(obj.virtual, proxy);
+            }
+        }
+        for (ObjectState obj : exitState.getStates()) {
+            ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
+            if (obj.isVirtual()) {
+                for (int i = 0; i < obj.getEntries().length; i++) {
+                    ValueNode value = obj.getEntry(i);
+                    ObjectState valueObj = exitState.getObjectState(value);
+                    if (valueObj == null) {
+                        if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
+                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
+                            obj.setEntry(i, proxy);
+                            effects.addFloatingNode(proxy, "virtualProxy");
+                        }
+                    }
+                }
+            } else {
+                if (initialObj == null || initialObj.isVirtual()) {
+                    ProxyNode proxy = proxies.get(obj.virtual);
+                    if (proxy == null) {
+                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null);
+                        effects.addFloatingNode(proxy, "proxy");
+                    } else {
+                        effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
+                        // nothing to do - will be handled in processNode
+                    }
+                    obj.updateMaterializedValue(proxy);
+                } else {
+                    if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
+                        Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
+                    }
+                }
+            }
+        }
+
+        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
+            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
+                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
+                effects.addFloatingNode(proxy, "readCacheProxy");
+                entry.setValue(proxy);
+            }
+        }
+    }
+
+    private static class MergeProcessor {
+
+        private final Block mergeBlock;
+        private final MergeNode merge;
+        private final NodeBitMap usages;
+        private final BlockMap<GraphEffectList> blockEffects;
+        private final GraphEffectList mergeEffects;
+        private final GraphEffectList afterMergeEffects;
+
+        private final HashMap<Object, PhiNode> materializedPhis = new HashMap<>();
+        private final IdentityHashMap<VirtualObjectNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
+        private final IdentityHashMap<PhiNode, PhiNode[]> valueObjectMergePhis = new IdentityHashMap<>();
+        private final IdentityHashMap<PhiNode, VirtualObjectNode> valueObjectVirtuals = new IdentityHashMap<>();
+        private BlockState newState;
+
+        public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap<GraphEffectList> blockEffects) {
+            this.usages = usages;
+            this.mergeBlock = mergeBlock;
+            this.blockEffects = blockEffects;
+            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.mergeEffects = new GraphEffectList();
+            this.afterMergeEffects = new GraphEffectList();
+        }
+
+        private <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+            PhiNode result = materializedPhis.get(virtual);
+            if (result == null) {
+                result = new PhiNode(kind, merge);
+                materializedPhis.put(virtual, result);
+            }
+            return result;
+        }
+
+        private PhiNode[] getValuePhis(VirtualObjectNode virtual) {
+            PhiNode[] result = valuePhis.get(virtual);
+            if (result == null) {
+                result = new PhiNode[virtual.entryCount()];
+                valuePhis.put(virtual, result);
+            }
+            return result;
+        }
+
+        private PhiNode[] getValueObjectMergePhis(PhiNode phi, int entryCount) {
+            PhiNode[] result = valueObjectMergePhis.get(phi);
+            if (result == null) {
+                result = new PhiNode[entryCount];
+                valueObjectMergePhis.put(phi, result);
+            }
+            return result;
+        }
+
+        private VirtualObjectNode getValueObjectVirtual(PhiNode phi, VirtualObjectNode virtual) {
+            VirtualObjectNode result = valueObjectVirtuals.get(phi);
+            if (result == null) {
+                result = virtual.duplicate();
+                valueObjectVirtuals.put(phi, result);
+            }
+            return result;
+        }
+
+        private void merge(List<BlockState> states) {
+            newState = BlockState.meetAliases(states);
+
+            /*
+             * Iterative processing: Merging the materialized/virtual state of virtual objects can
+             * lead to new materializations, which can lead to new materializations because of phis,
+             * and so on.
+             */
+
+            HashSet<VirtualObjectNode> virtualObjects = new HashSet<>(newState.getVirtualObjects());
+            boolean materialized;
+            do {
+                mergeEffects.clear();
+                afterMergeEffects.clear();
+                materialized = false;
+                for (VirtualObjectNode object : virtualObjects) {
+                    ObjectState[] objStates = new ObjectState[states.size()];
+                    for (int i = 0; i < states.size(); i++) {
+                        objStates[i] = states.get(i).getObjectState(object);
+                    }
                     int virtual = 0;
-                    ObjectState startObj = states.get(0).getObjectState(object);
+                    ObjectState startObj = objStates[0];
                     int lockCount = startObj.getLockCount();
                     boolean locksMatch = true;
                     ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue();
-                    for (BlockState state : states) {
-                        ObjectState obj = state.getObjectState(object);
+                    for (ObjectState obj : objStates) {
                         if (obj.isVirtual()) {
                             virtual++;
                             singleValue = null;
@@ -310,14 +521,15 @@
 
                     if (virtual < states.size()) {
                         if (singleValue == null) {
-                            PhiNode materializedValuePhi = new PhiNode(Kind.Object, merge);
-                            effects.addFloatingNode(materializedValuePhi);
+                            PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
+                            mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < states.size(); i++) {
                                 BlockState state = states.get(i);
-                                ObjectState obj = state.getObjectState(object);
+                                ObjectState obj = objStates[i];
                                 materialized |= obj.isVirtual();
-                                ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE);
-                                effects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
+                                Block predecessor = mergeBlock.getPredecessors().get(i);
+                                ensureMaterialized(state, obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
                             }
                             newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, lockCount));
                         } else {
@@ -326,428 +538,188 @@
                     } else {
                         assert virtual == states.size();
                         ValueNode[] values = startObj.getEntries().clone();
-                        PhiNode[] phis = new PhiNode[values.length];
-                        int mismatch = 0;
-                        for (int i = 1; i < states.size(); i++) {
-                            BlockState state = states.get(i);
-                            ValueNode[] fields = state.getObjectState(object).getEntries();
-                            for (int index = 0; index < values.length; index++) {
+                        PhiNode[] phis = getValuePhis(object);
+                        for (int index = 0; index < values.length; index++) {
+                            for (int i = 1; i < states.size(); i++) {
+                                ValueNode[] fields = objStates[i].getEntries();
                                 if (phis[index] == null && values[index] != fields[index]) {
-                                    mismatch++;
                                     phis[index] = new PhiNode(values[index].kind(), merge);
-                                    effects.addFloatingNode(phis[index]);
                                 }
                             }
                         }
-                        if (mismatch > 0) {
-                            for (int i = 0; i < states.size(); i++) {
-                                BlockState state = states.get(i);
-                                ValueNode[] fields = state.getObjectState(object).getEntries();
-                                for (int index = 0; index < values.length; index++) {
-                                    if (phis[index] != null) {
-                                        ObjectState obj = state.getObjectState(fields[index]);
-                                        if (obj != null) {
-                                            materialized |= obj.isVirtual();
-                                            ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE);
-                                            fields[index] = obj.getMaterializedValue();
-                                        }
-                                        effects.addPhiInput(phis[index], fields[index]);
+                        outer: for (int index = 0; index < values.length; index++) {
+                            if (phis[index] != null) {
+                                mergeEffects.addFloatingNode(phis[index], "virtualMergePhi");
+                                for (int i = 0; i < states.size(); i++) {
+                                    if (!objStates[i].isVirtual()) {
+                                        break outer;
                                     }
+                                    ValueNode[] fields = objStates[i].getEntries();
+                                    ObjectState obj = states.get(i).getObjectState(fields[index]);
+                                    if (obj != null) {
+                                        materialized |= obj.isVirtual();
+                                        Block predecessor = mergeBlock.getPredecessors().get(i);
+                                        ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                        fields[index] = obj.getMaterializedValue();
+                                    }
+                                    afterMergeEffects.addPhiInput(phis[index], fields[index]);
                                 }
-                            }
-                            for (int index = 0; index < values.length; index++) {
-                                if (phis[index] != null) {
-                                    values[index] = phis[index];
-                                }
+                                values[index] = phis[index];
                             }
                         }
                         newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, lockCount));
                     }
                 }
-            }
-
-            for (PhiNode phi : merge.phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    materialized |= processPhi(newState, merge, phi, states);
-                }
-            }
-        } while (materialized);
-
-        newState.mergeReadCache(states, merge, effects);
-
-        return newState;
-    }
 
-    private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List<BlockState> states) {
-        assert states.size() == phi.valueCount();
-        int virtualInputs = 0;
-        boolean materialized = false;
-        VirtualObjectNode sameObject = null;
-        ResolvedJavaType sameType = null;
-        int sameEntryCount = -1;
-        for (int i = 0; i < phi.valueCount(); i++) {
-            ValueNode value = phi.valueAt(i);
-            ObjectState obj = states.get(i).getObjectState(value);
-            if (obj != null) {
-                if (obj.isVirtual()) {
-                    virtualInputs++;
-                    if (i == 0) {
-                        sameObject = obj.virtual;
-                        sameType = obj.virtual.type();
-                        sameEntryCount = obj.virtual.entryCount();
-                    } else {
-                        if (sameObject != obj.virtual) {
-                            sameObject = null;
-                        }
-                        if (sameType != obj.virtual.type()) {
-                            sameType = null;
-                        }
-                        if (sameEntryCount != obj.virtual.entryCount()) {
-                            sameEntryCount = -1;
-                        }
+                for (PhiNode phi : merge.phis()) {
+                    if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
+                        materialized |= processPhi(phi, states);
                     }
-                } else {
-                    effects.setPhiInput(phi, i, obj.getMaterializedValue());
                 }
-            }
-        }
-        boolean materialize = false;
-        if (virtualInputs == 0) {
-            // nothing to do...
-        } else if (virtualInputs == phi.valueCount()) {
-            if (sameObject != null) {
-                newState.addAndMarkAlias(sameObject, phi, usages);
-            } else if (sameType != null && sameEntryCount != -1) {
-                materialize = true;
-                // throw new GraalInternalError("merge required for %s", sameType);
-            } else {
-                materialize = true;
-            }
-        } else {
-            materialize = true;
+            } while (materialized);
+
+            mergeReadCache(states);
         }
 
-        if (materialize) {
+        private boolean processPhi(PhiNode phi, List<BlockState> states) {
+            assert states.size() == phi.valueCount();
+            int virtualInputs = 0;
+            boolean materialized = false;
+            VirtualObjectNode sameObject = null;
+            ResolvedJavaType sameType = null;
+            int sameEntryCount = -1;
+            boolean hasIdentity = false;
             for (int i = 0; i < phi.valueCount(); i++) {
                 ValueNode value = phi.valueAt(i);
                 ObjectState obj = states.get(i).getObjectState(value);
                 if (obj != null) {
-                    materialized |= obj.isVirtual();
-                    replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj, METRIC_MATERIALIZATIONS_PHI);
-                }
-            }
-        }
-        return materialized;
-    }
-
-    @Override
-    protected BlockState cloneState(BlockState oldState) {
-        return oldState.cloneState();
-    }
-
-    @Override
-    protected List<BlockState> processLoop(Loop loop, BlockState initialState) {
-        GraphEffectList successEffects = new GraphEffectList();
-        HashSet<PhiDesc> phis = new HashSet<>();
-        for (int iteration = 0; iteration < 10; iteration++) {
-            BlockState state = initialState.cloneState();
-            int checkpoint = effects.checkpoint();
-
-            for (PhiDesc desc : phis) {
-                ObjectState obj = state.getObjectState(desc.virtualObject);
-                if (obj.isVirtual()) {
-                    ValueNode value = obj.getEntry(desc.fieldIndex);
-                    ObjectState valueObj = state.getObjectState(value);
-                    if (valueObj != null) {
-                        assert !valueObj.isVirtual();
-                        value = valueObj.getMaterializedValue();
-                    }
-
-                    PhiNode phiNode = new PhiNode(value.kind(), loop.loopBegin());
-                    effects.addFloatingNode(phiNode);
-                    effects.addPhiInput(phiNode, value);
-                    obj.setEntry(desc.fieldIndex, phiNode);
-                }
-            }
-
-            for (PhiNode phi : loop.loopBegin().phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    ObjectState initialObj = initialState.getObjectState(phi.valueAt(0));
-                    if (initialObj != null) {
-                        if (initialObj.isVirtual()) {
-                            state.addAndMarkAlias(initialObj.virtual, phi, usages);
+                    if (obj.isVirtual()) {
+                        virtualInputs++;
+                        if (i == 0) {
+                            sameObject = obj.virtual;
+                            sameType = obj.virtual.type();
+                            sameEntryCount = obj.virtual.entryCount();
                         } else {
-                            successEffects.setPhiInput(phi, 0, initialObj.getMaterializedValue());
+                            if (sameObject != obj.virtual) {
+                                sameObject = null;
+                            }
+                            if (sameType != obj.virtual.type()) {
+                                sameType = null;
+                            }
+                            if (sameEntryCount != obj.virtual.entryCount()) {
+                                sameEntryCount = -1;
+                            }
+                            hasIdentity |= obj.virtual.hasIdentity();
                         }
+                    } else {
+                        afterMergeEffects.setPhiInput(phi, i, obj.getMaterializedValue());
                     }
                 }
             }
-
-            effects.incLevel();
-            LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, state.cloneState());
-
-            List<BlockState> loopEndStates = info.endStates;
-            List<Block> predecessors = loop.header.getPredecessors();
-            HashSet<VirtualObjectNode> additionalMaterializations = new HashSet<>();
-            HashSet<ReadCacheEntry> additionalKilledReads = new HashSet<>();
-            int oldPhiCount = phis.size();
-            for (int i = 1; i < predecessors.size(); i++) {
-                processLoopEnd(loop.loopBegin(), (LoopEndNode) predecessors.get(i).getEndNode(), state, loopEndStates.get(i - 1), successEffects, additionalMaterializations, additionalKilledReads,
-                                phis);
-            }
-            if (additionalMaterializations.isEmpty() && additionalKilledReads.isEmpty() && oldPhiCount == phis.size()) {
-                effects.addAll(successEffects);
+            boolean materialize = false;
+            if (virtualInputs == 0) {
+                // nothing to do...
+            } else if (virtualInputs == phi.valueCount()) {
+                if (sameObject != null) {
+                    newState.addAndMarkAlias(sameObject, phi, usages);
+                } else if (sameType != null && sameEntryCount != -1) {
+                    if (!hasIdentity) {
+                        VirtualObjectNode virtual = getValueObjectVirtual(phi, states.get(0).getObjectState(phi.valueAt(0)).virtual);
 
-                assert info.exitStates.size() == loop.exits.size();
-                for (int i = 0; i < loop.exits.size(); i++) {
-                    BlockState exitState = info.exitStates.get(i);
-                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
-                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), state, exitState);
+                        PhiNode[] phis = getValueObjectMergePhis(phi, virtual.entryCount());
+                        for (int i = 0; i < virtual.entryCount(); i++) {
+                            assert virtual.entryKind(i) != Kind.Object;
+                            if (phis[i] == null) {
+                                phis[i] = new PhiNode(virtual.entryKind(i), merge);
+                            }
+                            mergeEffects.addFloatingNode(phis[i], "valueObjectPhi");
+                            for (int i2 = 0; i2 < phi.valueCount(); i2++) {
+                                afterMergeEffects.addPhiInput(phis[i], states.get(i2).getObjectState(phi.valueAt(i2)).getEntry(i));
+                            }
+                        }
+                        mergeEffects.addFloatingNode(virtual, "valueObjectNode");
+                        newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, 0));
+                        newState.addAndMarkAlias(virtual, virtual, usages);
+                        newState.addAndMarkAlias(virtual, phi, usages);
+                    } else {
+                        materialize = true;
+                    }
+                } else {
+                    materialize = true;
                 }
-
-                effects.decLevel();
-                return info.exitStates;
             } else {
-                successEffects.clear();
-                effects.backtrack(checkpoint);
-                effects.decLevel();
-                for (VirtualObjectNode virtualObject : additionalMaterializations) {
-                    ObjectState obj = initialState.getObjectState(virtualObject);
-                    if (obj.isVirtual()) {
-                        METRIC_MATERIALIZATIONS_LOOP_REITERATION.increment();
-                        initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, EscapeState.Global, effects);
-                    } else {
-                        assert obj.getState() == EscapeState.Global;
+                materialize = true;
+            }
+
+            if (materialize) {
+                for (int i = 0; i < phi.valueCount(); i++) {
+                    ValueNode value = phi.valueAt(i);
+                    ObjectState obj = states.get(i).getObjectState(value);
+                    if (obj != null) {
+                        materialized |= obj.isVirtual();
+                        Block predecessor = mergeBlock.getPredecessors().get(i);
+                        replaceWithMaterialized(value, phi, predecessor.getEndNode(), states.get(i), obj, blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_PHI);
                     }
                 }
-                for (ReadCacheEntry entry : additionalKilledReads) {
-                    initialState.getReadCache().remove(entry);
+            }
+            return materialized;
+        }
+
+        private void mergeReadCache(List<BlockState> states) {
+            for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                ReadCacheEntry key = entry.getKey();
+                ValueNode value = entry.getValue();
+                boolean phi = false;
+                for (int i = 1; i < states.size(); i++) {
+                    ValueNode otherValue = states.get(i).readCache.get(key);
+                    if (otherValue == null) {
+                        value = null;
+                        phi = false;
+                        break;
+                    }
+                    if (!phi && otherValue != value) {
+                        phi = true;
+                    }
+                }
+                if (phi) {
+                    PhiNode phiNode = getCachedPhi(entry, value.kind());
+                    mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
+                    for (int i = 0; i < states.size(); i++) {
+                        afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
+                    }
+                    newState.readCache.put(key, phiNode);
+                } else if (value != null) {
+                    newState.readCache.put(key, value);
+                }
+            }
+            for (PhiNode phi : merge.phis()) {
+                if (phi.kind() == Kind.Object) {
+                    for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                        if (entry.getKey().object == phi.valueAt(0)) {
+                            mergeReadCachePhi(phi, entry.getKey().identity, states);
+                        }
+                    }
+
                 }
             }
         }
 
-        throw new GraalInternalError("too many iterations at %s", loop);
-    }
-
-    private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) {
-        HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
-
-        for (ProxyNode proxy : exitNode.proxies()) {
-            ObjectState obj = exitState.getObjectState(proxy.value());
-            if (obj != null) {
-                proxies.put(obj.virtual, proxy);
-            }
-        }
-        for (ObjectState obj : exitState.getStates()) {
-            ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
-            if (obj.isVirtual()) {
-                for (int i = 0; i < obj.getEntries().length; i++) {
-                    ValueNode value = obj.getEntry(i);
-                    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) {
-                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
-                            obj.setEntry(i, proxy);
-                            effects.addFloatingNode(proxy);
-                        }
-                    }
+        private void mergeReadCachePhi(PhiNode phi, Object identity, List<BlockState> states) {
+            ValueNode[] values = new ValueNode[phi.valueCount()];
+            for (int i = 0; i < phi.valueCount(); i++) {
+                ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
+                if (value == null) {
+                    return;
                 }
-            } else {
-                if (initialObj == null || initialObj.isVirtual()) {
-                    ProxyNode proxy = proxies.get(obj.virtual);
-                    if (proxy == null) {
-                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null);
-                        effects.addFloatingNode(proxy);
-                    } else {
-                        effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
-                        // nothing to do - will be handled in processNode
-                    }
-                    obj.updateMaterializedValue(proxy);
-                } else {
-                    assert initialObj.getMaterializedValue() == obj.getMaterializedValue() : "materialized value is not allowed to change within loops: " + initialObj.getMaterializedValue() +
-                                    " vs. " + obj.getMaterializedValue() + " at " + exitNode;
-                }
-            }
-        }
-
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
-            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
-                effects.addFloatingNode(proxy);
-                entry.setValue(proxy);
+                values[i] = value;
             }
-        }
-    }
-
-    private final class PhiDesc {
-
-        public final VirtualObjectNode virtualObject;
-        public final int fieldIndex;
-
-        public PhiDesc(VirtualObjectNode virtualObject, int fieldIndex) {
-            this.virtualObject = virtualObject;
-            this.fieldIndex = fieldIndex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = fieldIndex;
-            result = prime * result + ((virtualObject == null) ? 0 : virtualObject.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null || getClass() != obj.getClass()) {
-                return false;
-            }
-            PhiDesc other = (PhiDesc) obj;
-            return virtualObject == other.virtualObject && fieldIndex == other.fieldIndex;
-        }
-    }
-
-    private void processLoopEnd(LoopBeginNode loopBegin, LoopEndNode loopEnd, BlockState initialState, BlockState loopEndState, GraphEffectList successEffects,
-                    Set<VirtualObjectNode> additionalMaterializations, HashSet<ReadCacheEntry> additionalKilledReads, HashSet<PhiDesc> phis) {
-        assert loopEnd.loopBegin() == loopBegin;
-        boolean materialized;
-        do {
-            materialized = false;
-            for (ObjectState state : initialState.getStates()) {
-                ObjectState endState = loopEndState.getObjectState(state.virtual);
-                if (state.isVirtual()) {
-                    if (endState.isVirtual()) {
-                        assert state.getEntries().length == endState.getEntries().length;
-                        for (int i = 0; endState.isVirtual() && i < state.getEntries().length; i++) {
-                            ValueNode value = state.getEntry(i);
-                            ValueNode endValue = endState.getEntry(i);
-                            ObjectState valueObj = initialState.getObjectState(value);
-                            ObjectState endValueObj = loopEndState.getObjectState(endValue);
 
-                            if (valueObj != null) {
-                                if (valueObj.isVirtual()) {
-                                    if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) {
-                                        additionalMaterializations.add(valueObj.virtual);
-                                    } else {
-                                        // endValue is also virtual and refers to the same virtual
-                                        // object, so we're
-                                        // good.
-                                    }
-                                }
-                            } else {
-                                if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) {
-                                    if (endValueObj != null) {
-                                        if (endValueObj.isVirtual()) {
-                                            METRIC_MATERIALIZATIONS_LOOP_END.increment();
-                                            loopEndState.materializeBefore(loopEnd, endValueObj.virtual, EscapeState.Global, successEffects);
-                                            materialized = true;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        additionalMaterializations.add(state.virtual);
-                    }
-                }
-            }
-            for (PhiNode phi : loopBegin.phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    ObjectState initialObj = initialState.getObjectState(phi.valueAt(0));
-                    boolean initialMaterialized = initialObj == null || !initialObj.isVirtual();
-
-                    ObjectState loopEndObj = loopEndState.getObjectState(phi.valueAt(loopEnd));
-                    if (loopEndObj == null || !loopEndObj.isVirtual()) {
-                        if (loopEndObj != null) {
-                            successEffects.setPhiInput(phi, loopBegin.phiPredecessorIndex(loopEnd), loopEndObj.getMaterializedValue());
-                        }
-                        if (!initialMaterialized) {
-                            additionalMaterializations.add(initialObj.virtual);
-                        }
-                    } else {
-                        if (initialMaterialized) {
-                            loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, EscapeState.Global, successEffects);
-                            materialized = true;
-                        } else {
-                            if (loopEndObj.virtual != initialObj.virtual) {
-                                additionalMaterializations.add(initialObj.virtual);
-                            }
-                        }
-                    }
-                }
+            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind());
+            mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
+            for (int i = 0; i < values.length; i++) {
+                afterMergeEffects.addPhiInput(phiNode, values[i]);
             }
-        } while (materialized);
-
-        for (ObjectState state : initialState.getStates()) {
-            ObjectState endState = loopEndState.getObjectState(state.virtual);
-            if (state.isVirtual()) {
-                if (endState.isVirtual()) {
-                    assert state.getEntries().length == endState.getEntries().length;
-                    for (int i = 0; i < state.getEntries().length; i++) {
-                        ValueNode value = state.getEntry(i);
-                        ValueNode endValue = endState.getEntry(i);
-                        ObjectState valueObj = initialState.getObjectState(value);
-                        ObjectState endValueObj = loopEndState.getObjectState(endValue);
-
-                        if (valueObj != null) {
-                            if (valueObj.isVirtual()) {
-                                if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) {
-                                    assert !additionalMaterializations.isEmpty();
-                                } else {
-                                    // endValue is also virtual and refers to the same virtual
-                                    // object, so we're
-                                    // good.
-                                }
-                            } else {
-                                if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) ||
-                                                (endValueObj == null && valueObj.getMaterializedValue() != endValue)) {
-                                    phis.add(new PhiDesc(state.virtual, i));
-                                } else {
-                                    // either endValue has the same materialized value as value or
-                                    // endValue is the
-                                    // same as the materialized value, so we're good.
-                                }
-                            }
-                        } else {
-                            if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) {
-                                if (endValueObj != null) {
-                                    if (endValueObj.isVirtual()) {
-                                        assert !additionalMaterializations.isEmpty();
-                                    }
-                                    successEffects.addPhiInput((PhiNode) value, endValueObj.getMaterializedValue());
-                                } else {
-                                    successEffects.addPhiInput((PhiNode) value, endValue);
-                                }
-                            } else if (value != endValue) {
-                                phis.add(new PhiDesc(state.virtual, i));
-                            }
-                        }
-                    }
-                } else {
-                    // endState.materializedValue != null
-                    assert !additionalMaterializations.isEmpty();
-                }
-            } else {
-                // state.materializedValue != null
-                if (endState.isVirtual()) {
-                    // throw new GraalInternalError("un-materialized object state at %s", loopEnd);
-                } else {
-                    if (state.getMaterializedValue() != endState.getMaterializedValue()) {
-                        // throw new
-                        // GraalInternalError("changed materialized value during loop: %s vs %s",
-                        // state.materializedValue, endState.materializedValue);
-                    }
-                }
-            }
-        }
-
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : initialState.getReadCache().entrySet()) {
-            if (loopEndState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                additionalKilledReads.add(entry.getKey());
-            }
+            newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode);
         }
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,13 +36,12 @@
 
 class VirtualizerToolImpl implements VirtualizerTool {
 
-    private final GraphEffectList effects;
     private final NodeBitMap usages;
     private final MetaAccessProvider metaAccess;
     private final Assumptions assumptions;
+    private GraphEffectList effects;
 
-    VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        this.effects = effects;
+    VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
         this.metaAccess = metaAccess;
         this.assumptions = assumptions;
@@ -52,7 +51,6 @@
     private boolean customAction;
     private BlockState state;
     private ValueNode current;
-    private int newVirtualObjectCount = 0;
 
     @Override
     public MetaAccessProvider getMetaAccessProvider() {
@@ -64,6 +62,10 @@
         return assumptions;
     }
 
+    public void setEffects(GraphEffectList effects) {
+        this.effects = effects;
+    }
+
     public void reset(BlockState newState, ValueNode newCurrent) {
         deleted = false;
         customAction = false;
@@ -79,10 +81,6 @@
         return customAction;
     }
 
-    public int getNewVirtualObjectCount() {
-        return newVirtualObjectCount;
-    }
-
     @Override
     public State getObjectState(ValueNode value) {
         return state.getObjectState(value);
@@ -155,7 +153,7 @@
         if (virtualObject.isAlive()) {
             state.addAndMarkAlias(virtualObject, virtualObject, usages);
         } else {
-            effects.addFloatingNode(virtualObject);
+            effects.addFloatingNode(virtualObject, "newVirtualObject");
         }
         for (int i = 0; i < entryState.length; i++) {
             entryState[i] = state.getScalarAlias(entryState[i]);
@@ -163,7 +161,6 @@
         state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount));
         state.addAndMarkAlias(virtualObject, virtualObject, usages);
         PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment();
-        newVirtualObjectCount++;
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -140,7 +141,7 @@
                     case READ:
                         assert arguments.size() == 2 || arguments.size() == 3;
                         Kind readKind = asKind(callTargetNode.returnType());
-                        Object readLocation = arguments.size() == 2 ? LocationNode.UNKNOWN_LOCATION : arguments.get(2).asConstant().asObject();
+                        Object readLocation = arguments.size() == 2 ? LocationNode.ANY_LOCATION : arguments.get(2).asConstant().asObject();
                         replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, readLocation));
                         break;
 
@@ -183,7 +184,7 @@
 
                     case TO_OBJECT:
                         assert arguments.size() == 1;
-                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp())));
+                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp())));
                         break;
 
                     default:
@@ -227,7 +228,7 @@
             Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class);
             ValueNode result = graph.add(constructor.newInstance(wordKind, left, right));
             if (result instanceof FixedWithNextNode) {
-                graph.addBeforeFixed(invoke.node(), (FixedWithNextNode) result);
+                graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) result);
             }
             return result;
         } catch (Throwable ex) {
@@ -267,28 +268,28 @@
 
     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, 1);
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
-        graph.addBeforeFixed(invoke.node(), read);
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp()));
+        graph.addBeforeFixed(invoke.asNode(), read);
         // The read must not float outside its block otherwise it may float above an explicit zero
         // check on its base address
-        read.dependencies().add(BeginNode.prevBegin(invoke.node()));
+        read.dependencies().add(BeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
     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, 1);
-        WriteNode write = graph.add(new WriteNode(base, value, location));
+        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE));
         write.setStateAfter(invoke.stateAfter());
-        graph.addBeforeFixed(invoke.node(), write);
+        graph.addBeforeFixed(invoke.asNode(), write);
         return write;
     }
 
     private static void replace(Invoke invoke, ValueNode value) {
         FixedNode next = invoke.next();
         invoke.setNext(null);
-        invoke.node().replaceAtPredecessor(next);
-        invoke.node().replaceAtUsages(value);
-        GraphUtil.killCFG(invoke.node());
+        invoke.asNode().replaceAtPredecessor(next);
+        invoke.asNode().replaceAtUsages(value);
+        GraphUtil.killCFG(invoke.asNode());
     }
 
     public boolean isWord(ValueNode node) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Apr 15 08:51:19 2013 +0200
@@ -80,9 +80,9 @@
                             ValueNode receiver = arguments.get(argc);
                             if (receiver == node && isWord(node)) {
                                 ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method);
-                                verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
+                                verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
                                 Operation operation = resolvedMethod.getAnnotation(Word.Operation.class);
-                                verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
+                                verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
                             }
                             argc++;
                         }
@@ -91,7 +91,7 @@
                             ValueNode argument = arguments.get(argc);
                             if (argument == node) {
                                 ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
-                                verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
+                                verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
                             }
                             argc++;
                         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Apr 15 08:51:19 2013 +0200
@@ -61,7 +61,7 @@
 
             dom = db.newDocument();
         } catch (ParserConfigurationException ex) {
-            System.out.println("Error while trying to instantiate DocumentBuilder " + ex);
+            throw new RuntimeException(ex);
         }
 
         graphDocument = dom.createElement("graphDocument");
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Mon Apr 15 08:51:19 2013 +0200
@@ -799,4 +799,8 @@
         return true;
     }
 
+    public static boolean isObject(TypeMirror actualType) {
+        return getQualifiedName(actualType).equals("java.lang.Object");
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Mon Apr 15 08:51:19 2013 +0200
@@ -103,19 +103,29 @@
         return annotations;
     }
 
-    /* Support JDK8 langtools. */
-    @SuppressWarnings("unused")
+    /**
+     * Support JDK8 langtools.
+     * 
+     * @param annotationType
+     */
     public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
         throw new UnsupportedOperationException();
     }
 
-    /* Support for some JDK8 builds. (remove after jdk8 is released) */
-    @SuppressWarnings("unused")
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     * 
+     * @param annotationType
+     */
     public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
         throw new UnsupportedOperationException();
     }
 
-    @Override
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     * 
+     * @param annotationType
+     */
     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 Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Mon Apr 15 08:51:19 2013 +0200
@@ -225,4 +225,7 @@
         return copy;
     }
 
+    public TypeMirror getReceiverType() {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java	Mon Apr 15 08:51:19 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.codegen.processor.ast;
 
+import java.lang.annotation.*;
 import java.util.*;
 
 import javax.lang.model.element.*;
@@ -92,4 +93,21 @@
 
     }
 
+    public List<? extends AnnotationMirror> getAnnotationMirrors() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Mon Apr 15 08:51:19 2013 +0200
@@ -117,7 +117,7 @@
         }
     }
 
-    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
+    private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
         CodeTreeBuilder builder = parent.create();
 
         boolean castedValues = sourceMethod != targetMethod;
@@ -153,6 +153,7 @@
                         break;
                     }
                 }
+                ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName());
                 assert parameter != null;
 
                 if (castedValues) {
@@ -160,12 +161,10 @@
                     if (field == null) {
                         builder.string(valueName(parameter));
                     } else {
-                        NodeData fieldNode = field.getNodeData();
-                        ExecutableTypeData execType = fieldNode.findExecutableType(parameter.getActualTypeData(node.getTypeSystem()));
-                        if (execType.hasUnexpectedValue(getContext())) {
+                        if (Utils.typeEquals(sourceParameter.getActualType(), parameter.getActualType())) {
+                            builder.string(valueName(parameter));
+                        } else {
                             builder.string(castValueName(parameter));
-                        } else {
-                            builder.string(valueName(parameter));
                         }
                     }
                 } else {
@@ -326,7 +325,7 @@
         return builder.getRoot();
     }
 
-    private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
         if (guardedSpecialization.getGuards().size() > 0) {
@@ -1476,7 +1475,12 @@
             builder.end(); // call replace
             builder.end(); // statement
 
-            String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization());
+            String generatedMethodName;
+            if (specialization.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
+                generatedMethodName = generatedGenericMethodName(null);
+            } else {
+                generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization());
+            }
             ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName);
 
             CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Mon Apr 15 08:51:19 2013 +0200
@@ -61,7 +61,7 @@
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("operation", getNode());
+        return createValueParameterSpec("returnValue", getNode());
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 15 08:51:19 2013 +0200
@@ -62,7 +62,9 @@
                 if (node != null) {
                     String dump = parsed.dump();
                     log.message(Kind.ERROR, null, null, null, dump);
+                    // CheckStyle: stop system..print check
                     System.out.println(dump);
+                    // CheckStyle: resume system..print check
                 }
             }
         } finally {
@@ -108,8 +110,7 @@
         }
 
         NodeData rootNode = parseNode(rootType);
-        boolean hasErrors = rootNode != null ? rootNode.hasErrors() : false;
-        if ((rootNode == null || hasErrors) && children.size() > 0) {
+        if (rootNode == null && children.size() > 0) {
             rootNode = new NodeData(rootType, rootType.getSimpleName().toString());
         }
 
@@ -152,6 +153,10 @@
 
         NodeData nodeData = parseNodeData(type, nodeType);
 
+        if (nodeData.hasErrors()) {
+            return nodeData; // error sync point
+        }
+
         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();) {
@@ -162,10 +167,6 @@
             }
         }
 
-        if (nodeData.hasErrors()) {
-            return nodeData; // error sync point
-        }
-
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type));
         nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements));
         if (nodeData.getExtensionElements() != null) {
@@ -328,6 +329,23 @@
         }
 
         if (genericSpecialization != null) {
+            if (genericSpecialization.isUseSpecializationsForGeneric()) {
+                for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) {
+                    if (Utils.isObject(parameter.getActualType())) {
+                        continue;
+                    }
+                    Set<String> types = new HashSet<>();
+                    for (SpecializationData specialization : specializations) {
+                        ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
+                        if (actualParameter != null) {
+                            types.add(Utils.getQualifiedName(actualParameter.getActualType()));
+                        }
+                    }
+                    if (types.size() > 1) {
+                        genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericType()));
+                    }
+                }
+            }
             TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(),
                             genericSpecialization.getParameters());
             // should not use messages from generic specialization
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Mon Apr 15 08:51:19 2013 +0200
@@ -194,4 +194,5 @@
     public String toString() {
         return String.format("%s [id = %s, method = %s, guards = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards());
     }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Mon Apr 15 08:51:19 2013 +0200
@@ -49,6 +49,10 @@
         this.localName = valueName;
     }
 
+    public ActualParameter(ActualParameter parameter, TypeMirror otherType) {
+        this(parameter.specification, otherType, parameter.index, parameter.implicit);
+    }
+
     public boolean isImplicit() {
         return implicit;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Mon Apr 15 08:51:19 2013 +0200
@@ -40,7 +40,7 @@
     private final MethodSpec specification;
     private final ExecutableElement method;
     private final AnnotationMirror markerAnnotation;
-    private final ActualParameter returnType;
+    private ActualParameter returnType;
     private List<ActualParameter> parameters;
 
     public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType,
@@ -104,6 +104,21 @@
         return returnType;
     }
 
+    public void replaceParameter(String localName, ActualParameter newParameter) {
+        if (returnType.getLocalName().equals(localName)) {
+            returnType = newParameter;
+            returnType.setMethod(this);
+        }
+
+        for (ListIterator<ActualParameter> iterator = parameters.listIterator(); iterator.hasNext();) {
+            ActualParameter parameter = iterator.next();
+            if (parameter.getLocalName().equals(localName)) {
+                iterator.set(newParameter);
+                newParameter.setMethod(this);
+            }
+        }
+    }
+
     public List<ActualParameter> getRequiredParameters() {
         List<ActualParameter> requiredParameters = new ArrayList<>();
         for (ActualParameter parameter : getParameters()) {
@@ -119,7 +134,7 @@
     }
 
     public ActualParameter findParameter(String valueName) {
-        for (ActualParameter param : getParameters()) {
+        for (ActualParameter param : getReturnTypeAndParameters()) {
             if (param.getLocalName().equals(valueName)) {
                 return param;
             }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Mon Apr 15 08:51:19 2013 +0200
@@ -37,7 +37,9 @@
 
     public static void run(InputStream input, PrintStream printOutput, int repeats, boolean log) {
         if (log) {
+            // CheckStyle: stop system..print check
             System.out.printf("== running on %s\n", Truffle.getRuntime().getName());
+            // CheckStyle: resume system..print check
         }
 
         NodeFactory factory = new NodeFactory(printOutput);
@@ -63,7 +65,9 @@
                     printOutput.println(result);
                 }
                 if (log) {
+                    // CheckStyle: stop system..print check
                     System.out.printf("== iteration %d: %.3f ms\n", (i + 1), (end - start) / 1000000.0);
+                    // CheckStyle: resume system..print check
                 }
             }
 
--- a/make/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/Makefile	Mon Apr 15 08:51:19 2013 +0200
@@ -582,6 +582,39 @@
 	 $(TAR) -cf - *) | \
 	 ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -)
 
+
+# Testing the built JVM
+RUN_JVM=JAVA_HOME=$(JDK_IMPORT_PATH) $(JDK_IMPORT_PATH)/bin/java -d$(ARCH_DATA_MODEL) -Dsun.java.launcher=gamma
+generic_test:
+	@$(ECHO) "Running with: $(ALTJVM_DIR)"
+	@$(RUN_JVM) -XXaltjvm=$(ALTJVM_DIR) -Xinternalversion
+	@$(RUN_JVM) -XXaltjvm=$(ALTJVM_DIR) -showversion -help
+
+# C2 test targets
+test_product test_optimized test_fastdebug test_jvmg:
+	@$(MAKE) generic_test ALTJVM_DIR="$(C2_DIR)/$(@:test_%=%)"
+
+# C1 test targets
+test_product1 test_optimized1 test_fastdebug1 test_jvmg1:
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	@$(MAKE) generic_test ALTJVM_DIR="$(C1_DIR)/$(@:test_%1=%)"
+  else
+	@$(ECHO) "No compiler1 ($(@:test_%=%)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
+  endif
+
+# Zero test targets
+test_productzero test_optimizedzero test_fastdebugzero test_jvmgzero:
+	@$(MAKE) generic_test ALTJVM_DIR="$(ZERO_DIR)/$(@:test_%zero=%)"
+
+# Shark test targets
+test_productshark test_optimizedshark test_fastdebugshark test_jvmgshark:
+	@$(MAKE) generic_test ALTJVM_DIR="$(SHARK_DIR)/$(@:test_%shark=%)"
+
+# Minimal1 test targets
+test_productminimal1 test_optimizedminimal1 test_fastdebugminimal1 test_jvmgminimal1:
+	@$(MAKE) generic_test ALTJVM_DIR="$(MINIMAL1_DIR)/$(@:test_%minimal1=%)"
+
+
 test_jdk:
   ifeq ($(JVM_VARIANT_CLIENT), true)
 	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -client -Xinternalversion
--- a/make/bsd/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/Makefile	Mon Apr 15 08:51:19 2013 +0200
@@ -306,63 +306,42 @@
 
 $(TARGETS_C2):  $(SUBDIRS_C2)
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_TIERED):  $(SUBDIRS_TIERED)
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_C1):  $(SUBDIRS_C1)
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_CORE):  $(SUBDIRS_CORE)
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_ZERO):  $(SUBDIRS_ZERO)
 	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_SHARK):  $(SUBDIRS_SHARK)
 	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_MINIMAL1):  $(SUBDIRS_MINIMAL1)
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
--- a/make/bsd/build.sh	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-#! /bin/sh
-#
-# Copyright (c) 1999, 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.
-#  
-#
-
-# Make sure the variable JAVA_HOME is set before running this script.
-
-set -u
-
-
-if [ $# != 2 ]; then 
-    echo "Usage : $0 Build_Options Location"
-    echo "Build Options : debug or optimized or basicdebug or basic or clean"
-    echo "Location : specify any workspace which has gamma sources"
-    exit 1
-fi
-
-# Just in case:
-case ${JAVA_HOME} in
-/*) true;;
-?*) JAVA_HOME=`( cd $JAVA_HOME; pwd )`;;
-esac
-
-case `uname -m` in
-  i386|i486|i586|i686)
-    mach=i386
-    ;;
-  *)
-    echo "Unsupported machine: " `uname -m`
-    exit 1
-    ;;
-esac
-
-if [ "${JAVA_HOME}" = ""  -o  ! -d "${JAVA_HOME}" -o ! -d ${JAVA_HOME}/jre/lib/${mach} ]; then
-    echo "JAVA_HOME needs to be set to a valid JDK path"
-    echo "ksh : export JAVA_HOME=/net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd"
-    echo "csh : setenv JAVA_HOME /net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd"
-    exit 1
-fi
-
-
-LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/`uname -p`:\
-${JAVA_HOME}/jre/lib/`uname -p`/native_threads:${LD_LIBRARY_PATH-.}
-
-# This is necessary as long as we are using the old launcher
-# with the new distribution format:
-CLASSPATH=${JAVA_HOME}/jre/lib/rt.jar:${CLASSPATH-.}
-
-
-for gm in gmake gnumake
-do
-  if [ "${GNUMAKE-}" != "" ]; then break; fi
-  ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm
-done
-: ${GNUMAKE:?'Cannot locate the gnumake program.  Stop.'}
-
-
-echo "### ENVIRONMENT SETTINGS:"
-export JAVA_HOME		; echo "JAVA_HOME=$JAVA_HOME"
-export LD_LIBRARY_PATH		; echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
-export CLASSPATH		; echo "CLASSPATH=$CLASSPATH"
-export GNUMAKE			; echo "GNUMAKE=$GNUMAKE"
-echo "###"
-
-Build_Options=$1
-Location=$2
-
-case ${Location} in
-/*) true;;
-?*) Location=`(cd ${Location}; pwd)`;;
-esac
-
-echo \
-${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location}
-${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location}
--- a/make/bsd/makefiles/buildtree.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/buildtree.make	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -50,7 +50,6 @@
 # jvmti.make	- generate JVMTI bindings from the spec (JSR-163)
 # sa.make	- generate SA jar file and natives
 # env.[ck]sh	- environment settings
-# test_gamma	- script to run the Queens program
 # 
 # The makefiles are split this way so that "make foo" will run faster by not
 # having to read the dependency files for the vm.
@@ -67,9 +66,6 @@
 # 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details.
 QUIETLY$(MAKE_VERBOSE)	= @
 
-# For now, until the compiler is less wobbly:
-TESTFLAGS	= -Xbatch -showversion
-
 ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
 else
@@ -135,7 +131,7 @@
 # dtrace.make is used on BSD versions that implement Dtrace (like MacOS X)
 BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make \
 	jvmti.make sa.make dtrace.make \
-        env.sh env.csh jdkpath.sh .dbxrc test_gamma
+        env.sh env.csh jdkpath.sh
 
 BUILDTREE_VARS	= GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
 	SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
@@ -194,6 +190,17 @@
 # literal "$(GAMMADIR)/" suitable for inclusion in a Makefile.  
 gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2)))
 
+# This bit is needed to enable local rebuilds.
+# Unless the makefile itself sets LP64, any environmental
+# setting of LP64 will interfere with the build.
+LP64_SETTING/32 = LP64 = \#empty
+LP64_SETTING/64 = LP64 = 1
+
+DATA_MODE/i486 = 32
+DATA_MODE/amd64 = 64
+
+DATA_MODE = $(DATA_MODE/$(BUILDARCH))
+
 flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
@@ -216,6 +223,7 @@
 	echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \
 	echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \
 	echo "OPENJDK = $(OPENJDK)"; \
+	echo "$(LP64_SETTING/$(DATA_MODE))"; \
 	echo; \
 	echo "# Used for platform dispatching"; \
 	echo "TARGET_DEFINES  = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
@@ -352,7 +360,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
+	{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
 	{ \
 	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; \
@@ -364,8 +372,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && \
-	{ echo "if (! \$$?JAVA_HOME) setenv JAVA_HOME \"$$JAVA_HOME\""; }; \
+	{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
 	sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
 	) > $@
 
@@ -376,119 +383,6 @@
 	echo "JDK=${JAVA_HOME}"; \
 	) > $@	   
 
-.dbxrc:  $(BUILDTREE_MAKE)
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "echo '# Loading $(PLATFORM_DIR)/$(TARGET)/.dbxrc'"; \
-	echo "if [ -f \"\$${HOTSPOT_DBXWARE}\" ]"; \
-	echo "then"; \
-	echo "	source \"\$${HOTSPOT_DBXWARE}\""; \
-	echo "elif [ -f \"\$$HOME/.dbxrc\" ]"; \
-	echo "then"; \
-	echo "	source \"\$$HOME/.dbxrc\""; \
-	echo "fi"; \
-	) > $@
-
-# Skip the test for product builds (which only work when installed in a JDK), to
-# avoid exiting with an error and causing make to halt.
-NO_TEST_MSG	= \
-	echo "$@:  skipping the test--this build must be tested in a JDK."
-
-NO_JAVA_HOME_MSG	= \
-	echo "JAVA_HOME must be set to run this test."
-
-DATA_MODE = $(DATA_MODE/$(BUILDARCH))
-JAVA_FLAG = $(JAVA_FLAG/$(DATA_MODE))
-
-DATA_MODE/i486    = 32
-DATA_MODE/sparc   = 32
-DATA_MODE/sparcv9 = 64
-DATA_MODE/amd64   = 64
-DATA_MODE/ia64    = 64
-DATA_MODE/zero    = $(ARCH_DATA_MODEL)
-
-JAVA_FLAG/32 = -d32
-JAVA_FLAG/64 = -d64
-
-WRONG_DATA_MODE_MSG = \
-	echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK."
-
-CROSS_COMPILING_MSG = \
-	echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run."
-
-test_gamma:  $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "#!/bin/sh"; \
-	echo ""; \
-	$(BUILDTREE_COMMENT); \
-	echo ""; \
-	echo "# Include environment settings for gamma run"; \
-	echo ""; \
-	echo ". ./env.sh"; \
-	echo ""; \
-	echo "# Do not run gamma test for cross compiles"; \
-	echo ""; \
-	echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \
-	echo "  $(CROSS_COMPILING_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Make sure JAVA_HOME is set as it is required for gamma"; \
-	echo ""; \
-	echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \
-	echo "  $(NO_JAVA_HOME_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Check JAVA_HOME version to be used for the test"; \
-	echo ""; \
-	echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \
-	echo "if [ \$$? -ne 0 ]; then "; \
-	echo "  $(WRONG_DATA_MODE_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "GAMMA_PROG=gamma"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  # Ensure architecture for gamma and JAVA_HOME is the same."; \
-	echo "  # NOTE: gamma assumes the OpenJDK directory layout."; \
-	echo ""; \
-	echo "  GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \
-	echo "  JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  if [ ! -f \$${JVM_LIB} ]; then"; \
-	echo "    JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  fi"; \
-	echo "  if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \
-	echo "    $(WRONG_DATA_MODE_MSG)"; \
-	echo "    exit 0"; \
-	echo "  fi"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Compile Queens program for test"; \
-	echo ""; \
-	echo "rm -f Queens.class"; \
-	echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \
-	echo ""; \
-	echo "# Set library path solely for gamma launcher test run"; \
-	echo ""; \
-	echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "export LD_LIBRARY_PATH"; \
-	echo "unset LD_LIBRARY_PATH_32"; \
-	echo "unset LD_LIBRARY_PATH_64"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "  export DYLD_LIBRARY_PATH"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Use the gamma launcher and JAVA_HOME to run the test"; \
-	echo ""; \
-	echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \
-	) > $@
-	$(QUIETLY) chmod +x $@
-
 FORCE:
 
 .PHONY:  all FORCE
--- a/make/bsd/makefiles/compiler1.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/compiler1.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
\ No newline at end of file
--- a/make/bsd/makefiles/compiler2.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/compiler2.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/bsd/makefiles/gcc.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/gcc.make	Mon Apr 15 08:51:19 2013 +0200
@@ -168,12 +168,12 @@
 # conversions which might affect the values. To avoid that, we need to turn
 # it off explicitly. 
 ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
-ACCEPTABLE_WARNINGS = -Wpointer-arith -Wsign-compare
+WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef
 else
-ACCEPTABLE_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare
+WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef
 endif
 
-CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ACCEPTABLE_WARNINGS)
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
 # Special cases
 CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) 
 # XXXDARWIN: for _dyld_bind_fully_image_containing_address
@@ -229,6 +229,20 @@
 CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
 endif
 
+ifeq ($(OS_VENDOR), Darwin)
+  # Setting these parameters makes it an error to link to macosx APIs that are 
+  # newer than the given OS version and makes the linked binaries compatible even
+  # if built on a newer version of the OS.
+  # The expected format is X.Y.Z
+  ifeq ($(MACOSX_VERSION_MIN),)
+    MACOSX_VERSION_MIN=10.7.0
+  endif
+  # The macro takes the version with no dots, ex: 1070
+  CFLAGS += -DMAC_OS_X_VERSION_MAX_ALLOWED=$(subst .,,$(MACOSX_VERSION_MIN)) \
+            -mmacosx-version-min=$(MACOSX_VERSION_MIN)
+  LDFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN)
+endif
+
 #------------------------------------------------------------------------
 # Linker flags
 
--- a/make/bsd/makefiles/mapfile-vers-debug	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/mapfile-vers-debug	Mon Apr 15 08:51:19 2013 +0200
@@ -135,6 +135,7 @@
                 JVM_GetEnclosingMethodInfo;
                 JVM_GetFieldAnnotations;
                 JVM_GetFieldIxModifiers;
+                JVM_GetFieldTypeAnnotations;
                 JVM_GetHostName;
                 JVM_GetInheritedAccessControlContext;
                 JVM_GetInterfaceVersion;
@@ -156,6 +157,7 @@
                 JVM_GetMethodIxSignatureUTF;
                 JVM_GetMethodParameterAnnotations;
                 JVM_GetMethodParameters;
+                JVM_GetMethodTypeAnnotations;
                 JVM_GetPrimitiveArrayElement;
                 JVM_GetProtectionDomain;
                 JVM_GetSockName;
--- a/make/bsd/makefiles/mapfile-vers-product	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/mapfile-vers-product	Mon Apr 15 08:51:19 2013 +0200
@@ -135,6 +135,7 @@
                 JVM_GetEnclosingMethodInfo;
                 JVM_GetFieldAnnotations;
                 JVM_GetFieldIxModifiers;
+                JVM_GetFieldTypeAnnotations;
                 JVM_GetHostName;
                 JVM_GetInheritedAccessControlContext;
                 JVM_GetInterfaceVersion;
@@ -156,6 +157,7 @@
                 JVM_GetMethodIxSignatureUTF;
                 JVM_GetMethodParameterAnnotations;
                 JVM_GetMethodParameters;
+                JVM_GetMethodTypeAnnotations;
                 JVM_GetPrimitiveArrayElement;
                 JVM_GetProtectionDomain;
                 JVM_GetSockName;
--- a/make/bsd/makefiles/saproc.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/saproc.make	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -24,7 +24,7 @@
 
 # Rules to build serviceability agent library, used by vm.make
 
-# libsaproc.so: serviceability agent
+# libsaproc.so(dylib): serviceability agent
 SAPROC   = saproc
 
 ifeq ($(OS_VENDOR), Darwin)
@@ -37,7 +37,7 @@
 
 SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)
 
-NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c                 \
+BSD_NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c             \
                       $(SASRCDIR)/symtab.c                   \
                       $(SASRCDIR)/libproc_impl.c             \
                       $(SASRCDIR)/ps_proc.c                  \
@@ -45,13 +45,19 @@
                       $(SASRCDIR)/BsdDebuggerLocal.c         \
                       $(AGENT_DIR)/src/share/native/sadis.c
 
+DARWIN_NON_STUB_SASRCFILES = $(SASRCDIR)/symtab.c            \
+                      $(SASRCDIR)/libproc_impl.c             \
+                      $(SASRCDIR)/ps_core.c                  \
+                      $(SASRCDIR)/MacosxDebuggerLocal.m      \
+                      $(AGENT_DIR)/src/share/native/sadis.c
+
 ifeq ($(OS_VENDOR), FreeBSD)
-  SASRCFILES = $(NON_STUB_SASRCFILES)
+  SASRCFILES = $(BSD_NON_STUB_SASRCFILES)
   SALIBS = -lutil -lthread_db
   SAARCH = $(ARCHFLAG)
 else
   ifeq ($(OS_VENDOR), Darwin)
-    SASRCFILES = $(SASRCDIR)/MacosxDebuggerLocal.m
+    SASRCFILES = $(DARWIN_NON_STUB_SASRCFILES)
     SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
     #objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles?
     SAARCH = $(subst -march=i586,,$(ARCHFLAG))
@@ -102,7 +108,7 @@
 	fi
 	@echo Making SA debugger back-end...
 	$(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE                   \
-                   $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG)     \
+	           $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG)       \
 	           -I$(SASRCDIR)                                        \
 	           -I$(GENERATED)                                       \
 	           $(BOOT_JAVA_INCLUDES)                                \
--- a/make/bsd/makefiles/tiered.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/bsd/makefiles/tiered.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/build-graal.xml	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/build-graal.xml	Mon Apr 15 08:51:19 2013 +0200
@@ -29,16 +29,16 @@
   <property name="jar.dir" value="${shared.dir}"/>
   <property name="jar.file" value="${jar.dir}/graal.jar"/>
   <target depends="jar" name="main"/>
-  <target name="compile">
+  <target depends="cleanclasses" 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.api.replacements"/>
       <src path="${src.dir}/com.oracle.graal.nodes"/>
       <src path="${src.dir}/com.oracle.graal.phases"/>
-      <src path="${src.dir}/com.oracle.graal.api.replacements"/>
       <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"/>
@@ -76,8 +76,10 @@
     <mkdir dir="${jar.dir}"/>
     <jar basedir="${classes.dir}" destfile="${jar.file}"/>
   </target>
-  <target name="clean">
+  <target name="cleanclasses">
     <delete dir="${classes.dir}"/>
-    <delete file="${jar.filr}"/>
+  </target>
+  <target depends="cleanclasses" name="clean">
+    <delete file="${jar.file}"/>
   </target>
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/build.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,92 @@
+#! /bin/sh
+#
+# 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
+# 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.
+#  
+#
+
+# Make sure the variable JAVA_HOME is set before running this script.
+
+set -u
+
+
+if [ $# -lt 1 ]; then 
+    echo "Usage : $0 BuildTarget [LP64=1] [BuildOptions]"
+    echo "               Server VM | Client VM"
+    echo "BuildTarget :  debug     | debug1"
+    echo "               fastdebug | fastdebug1"
+    echo "               jvmg      | jvmg1"
+    echo "               optimized | optimized1"
+    echo "               profiled  | profiled1"
+    echo "               product   | product1"
+    exit 1
+fi
+
+if [ "${JAVA_HOME-}" = ""  -o  ! -d "${JAVA_HOME-}" -o ! -d ${JAVA_HOME-}/jre/lib/ ]; then
+    echo "JAVA_HOME needs to be set to a valid JDK path"
+    echo "JAVA_HOME: ${JAVA_HOME-}"
+    exit 1
+fi
+
+# Just in case:
+JAVA_HOME=`( cd $JAVA_HOME; pwd )`
+
+if [ "${ALT_BOOTDIR-}" = ""  -o  ! -d "${ALT_BOOTDIR-}" -o ! -d ${ALT_BOOTDIR-}/jre/lib/ ]; then
+    ALT_BOOTDIR=${JAVA_HOME}
+fi
+
+# build in current directory by default
+if [ "${ALT_OUTPUTDIR-}" = ""  -o  ! -d "${ALT_OUTPUTDIR-}" ]; then
+    ALT_OUTPUTDIR=`(pwd)`
+fi
+
+HOTSPOT_SRC=`(dirname $0)`/..
+HOTSPOT_SRC=`(cd ${HOTSPOT_SRC}; pwd)`
+
+for gm in gmake gnumake
+do
+  if [ "${GNUMAKE-}" != "" ]; then break; fi
+  ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm
+done
+: ${GNUMAKE:?'Cannot locate the gnumake program.  Stop.'}
+
+# quiet build by default
+Quiet="MAKE_VERBOSE="
+
+# no debug info by default
+NoDebugInfo="ENABLE_FULL_DEBUG_SYMBOLS="
+
+LANG=C
+
+echo "### ENVIRONMENT SETTINGS:"
+export HOTSPOT_SRC		; echo "HOTSPOT_SRC=$HOTSPOT_SRC"
+export JAVA_HOME		; echo "JAVA_HOME=$JAVA_HOME"
+export ALT_BOOTDIR		; echo "ALT_BOOTDIR=$ALT_BOOTDIR"
+export ALT_OUTPUTDIR		; echo "ALT_OUTPUTDIR=$ALT_OUTPUTDIR"
+export GNUMAKE			; echo "GNUMAKE=$GNUMAKE"
+export LANG			; echo "LANG=$LANG"
+echo "###"
+
+BuildOptions="$Quiet $NoDebugInfo $*"
+
+echo \
+${GNUMAKE} -f ${HOTSPOT_SRC}/make/Makefile $BuildOptions GAMMADIR=${HOTSPOT_SRC}
+${GNUMAKE} -f ${HOTSPOT_SRC}/make/Makefile $BuildOptions GAMMADIR=${HOTSPOT_SRC}
--- a/make/defs.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/defs.make	Mon Apr 15 08:51:19 2013 +0200
@@ -329,7 +329,7 @@
 endif
 
 # Required make macro settings for all platforms
-MAKE_ARGS += JAVA_HOME=$(ABS_BOOTDIR)
+MAKE_ARGS += BOOTDIR=$(ABS_BOOTDIR)
 MAKE_ARGS += OUTPUTDIR=$(ABS_OUTPUTDIR)
 MAKE_ARGS += GAMMADIR=$(ABS_GAMMADIR)
 MAKE_ARGS += MAKE_VERBOSE=$(MAKE_VERBOSE)
@@ -365,9 +365,6 @@
 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
-
 ifndef JAVASE_EMBEDDED
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h
 endif
--- a/make/excludeSrc.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/excludeSrc.make	Mon Apr 15 08:51:19 2013 +0200
@@ -28,7 +28,8 @@
       Src_Files_EXCLUDE += jvmtiGetLoadedClasses.cpp forte.cpp jvmtiThreadState.cpp jvmtiExtensions.cpp \
 	jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \
 	jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \
-	jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp
+	jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \
+	jvmtiClassFileReconstituter.cpp
 endif
 
 ifeq ($(INCLUDE_FPROF), false)
@@ -69,7 +70,7 @@
       CXXFLAGS += -DINCLUDE_CDS=0
       CFLAGS += -DINCLUDE_CDS=0
 
-      Src_Files_EXCLUDE += metaspaceShared.cpp
+      Src_Files_EXCLUDE += filemap.cpp metaspaceShared.cpp
 endif
 
 ifeq ($(INCLUDE_ALL_GCS), false)
--- a/make/hotspot_version	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/hotspot_version	Mon Apr 15 08:51:19 2013 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=25
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=21
+HS_BUILD_NUMBER=28
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/jprt.properties	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/jprt.properties	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -97,15 +97,18 @@
 jprt.my.linux.ppcsflt.jdk7u8=${jprt.my.linux.ppcsflt.jdk7}
 jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}}
 
-jprt.my.linux.armvfp.jdk8=linux_armvfp_2.6
-jprt.my.linux.armvfp.jdk7=linux_armvfp_2.6
-jprt.my.linux.armvfp.jdk7u8=${jprt.my.linux.armvfp.jdk7}
-jprt.my.linux.armvfp=${jprt.my.linux.armvfp.${jprt.tools.default.release}}
+jprt.my.linux.armvfpsflt.jdk8=linux_armvfpsflt_2.6
+jprt.my.linux.armvfpsflt=${jprt.my.linux.armvfpsflt.${jprt.tools.default.release}}
+
+jprt.my.linux.armvfphflt.jdk8=linux_armvfphflt_2.6
+jprt.my.linux.armvfphflt=${jprt.my.linux.armvfphflt.${jprt.tools.default.release}}
 
-jprt.my.linux.armv6.jdk8=linux_armv6_2.6
-jprt.my.linux.armv6.jdk7=linux_armv6_2.6
-jprt.my.linux.armv6.jdk7u8=${jprt.my.linux.armv6.jdk7}
-jprt.my.linux.armv6=${jprt.my.linux.armv6.${jprt.tools.default.release}}
+# The ARM GP vfp-sflt build is not currently supported
+#jprt.my.linux.armvs.jdk8=linux_armvs_2.6
+#jprt.my.linux.armvs=${jprt.my.linux.armvs.${jprt.tools.default.release}}
+
+jprt.my.linux.armvh.jdk8=linux_armvh_2.6
+jprt.my.linux.armvh=${jprt.my.linux.armvh.${jprt.tools.default.release}}
 
 jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6
@@ -139,7 +142,7 @@
     ${jprt.my.macosx.x64}-{product|fastdebug|debug}, \
     ${jprt.my.windows.i586}-{product|fastdebug|debug}, \
     ${jprt.my.windows.x64}-{product|fastdebug|debug}, \
-    ${jprt.my.linux.armv6}-{product|fastdebug}
+    ${jprt.my.linux.armvh}-{product|fastdebug}
 
 jprt.build.targets.open= \
     ${jprt.my.solaris.i586}-{productOpen}, \
@@ -151,7 +154,8 @@
     ${jprt.my.linux.ppc}-{productEmb|fastdebugEmb}, \
     ${jprt.my.linux.ppcv2}-{productEmb|fastdebugEmb}, \
     ${jprt.my.linux.ppcsflt}-{productEmb|fastdebugEmb}, \
-    ${jprt.my.linux.armvfp}-{productEmb|fastdebugEmb}, \
+    ${jprt.my.linux.armvfpsflt}-{productEmb|fastdebugEmb}, \
+    ${jprt.my.linux.armvfphflt}-{productEmb|fastdebugEmb}, \
     ${jprt.my.linux.armsflt}-{productEmb|fastdebugEmb}
 
 jprt.build.targets.all=${jprt.build.targets.standard}, \
--- a/make/linux/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/Makefile	Mon Apr 15 08:51:19 2013 +0200
@@ -306,63 +306,42 @@
 
 $(TARGETS_C2):  $(SUBDIRS_C2)
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_TIERED):  $(SUBDIRS_TIERED)
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_C1):  $(SUBDIRS_C1)
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_CORE):  $(SUBDIRS_CORE)
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_ZERO):  $(SUBDIRS_ZERO)
 	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_SHARK):  $(SUBDIRS_SHARK)
 	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_MINIMAL1):  $(SUBDIRS_MINIMAL1)
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
--- a/make/linux/build.sh	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-#! /bin/sh
-#
-# Copyright (c) 1999, 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.
-#  
-#
-
-# Make sure the variable JAVA_HOME is set before running this script.
-
-set -u
-
-
-if [ $# != 2 ]; then 
-    echo "Usage : $0 Build_Options Location"
-    echo "Build Options : debug or optimized or basicdebug or basic or clean"
-    echo "Location : specify any workspace which has gamma sources"
-    exit 1
-fi
-
-# Just in case:
-case ${JAVA_HOME} in
-/*) true;;
-?*) JAVA_HOME=`( cd $JAVA_HOME; pwd )`;;
-esac
-
-case `uname -m` in
-  i386|i486|i586|i686)
-    mach=i386
-    ;;
-  x86_64)
-    mach=amd64
-    ;;
-  *)
-    echo "Unsupported machine: " `uname -m`
-    exit 1
-    ;;
-esac
-
-if [ "${JAVA_HOME}" = ""  -o  ! -d "${JAVA_HOME}" -o ! -d ${JAVA_HOME}/jre/lib/${mach} ]; then
-    echo "JAVA_HOME needs to be set to a valid JDK path"
-    echo "ksh : export JAVA_HOME=/net/tetrasparc/export/gobi/JDK1.2_fcs_V/linux"
-    echo "csh : setenv JAVA_HOME /net/tetrasparc/export/gobi/JDK1.2_fcs_V/linux"
-    exit 1
-fi
-
-
-LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/`uname -p`:\
-${JAVA_HOME}/jre/lib/`uname -p`/native_threads:${LD_LIBRARY_PATH-.}
-
-# This is necessary as long as we are using the old launcher
-# with the new distribution format:
-CLASSPATH=${JAVA_HOME}/jre/lib/rt.jar:${CLASSPATH-.}
-
-
-for gm in gmake gnumake
-do
-  if [ "${GNUMAKE-}" != "" ]; then break; fi
-  ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm
-done
-: ${GNUMAKE:?'Cannot locate the gnumake program.  Stop.'}
-
-
-echo "### ENVIRONMENT SETTINGS:"
-export JAVA_HOME		; echo "JAVA_HOME=$JAVA_HOME"
-export LD_LIBRARY_PATH		; echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
-export CLASSPATH		; echo "CLASSPATH=$CLASSPATH"
-export GNUMAKE			; echo "GNUMAKE=$GNUMAKE"
-echo "###"
-
-Build_Options=$1
-Location=$2
-
-case ${Location} in
-/*) true;;
-?*) Location=`(cd ${Location}; pwd)`;;
-esac
-
-echo \
-${GNUMAKE} -f ${Location}/make/linux/Makefile $Build_Options GAMMADIR=${Location}
-${GNUMAKE} -f ${Location}/make/linux/Makefile $Build_Options GAMMADIR=${Location}
--- a/make/linux/makefiles/buildtree.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/buildtree.make	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -50,7 +50,6 @@
 # jvmti.make	- generate JVMTI bindings from the spec (JSR-163)
 # sa.make	- generate SA jar file and natives
 # env.[ck]sh	- environment settings
-# test_gamma	- script to run the Queens program
 # 
 # The makefiles are split this way so that "make foo" will run faster by not
 # having to read the dependency files for the vm.
@@ -64,9 +63,6 @@
 # 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details.
 QUIETLY$(MAKE_VERBOSE)	= @
 
-# For now, until the compiler is less wobbly:
-TESTFLAGS	= -Xbatch -showversion
-
 ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
 else
@@ -128,7 +124,7 @@
 BUILDTREE_MAKE	= $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
 
 BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \
-        env.sh env.csh jdkpath.sh .dbxrc test_gamma
+        env.sh env.csh jdkpath.sh
 
 BUILDTREE_VARS	= GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
 	SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
@@ -187,6 +183,19 @@
 # literal "$(GAMMADIR)/" suitable for inclusion in a Makefile.  
 gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2)))
 
+# This bit is needed to enable local rebuilds.
+# Unless the makefile itself sets LP64, any environmental
+# setting of LP64 will interfere with the build.
+LP64_SETTING/32 = LP64 = \#empty
+LP64_SETTING/64 = LP64 = 1
+
+DATA_MODE/i486 = 32
+DATA_MODE/sparc = 32
+DATA_MODE/sparcv9 = 64
+DATA_MODE/amd64 = 64
+
+DATA_MODE = $(DATA_MODE/$(BUILDARCH))
+
 flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
@@ -209,6 +218,7 @@
 	echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \
 	echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \
 	echo "OPENJDK = $(OPENJDK)"; \
+	echo "$(LP64_SETTING/$(DATA_MODE))"; \
 	echo; \
 	echo "# Used for platform dispatching"; \
 	echo "TARGET_DEFINES  = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
@@ -345,7 +355,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
+	{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
 	{ \
 	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; \
@@ -357,8 +367,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && \
-	{ echo "if (! \$$?JAVA_HOME) setenv JAVA_HOME \"$$JAVA_HOME\""; }; \
+	{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
 	sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
 	) > $@
 
@@ -369,119 +378,6 @@
 	echo "JDK=${JAVA_HOME}"; \
 	) > $@	   
 
-.dbxrc:  $(BUILDTREE_MAKE)
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "echo '# Loading $(PLATFORM_DIR)/$(TARGET)/.dbxrc'"; \
-	echo "if [ -f \"\$${HOTSPOT_DBXWARE}\" ]"; \
-	echo "then"; \
-	echo "	source \"\$${HOTSPOT_DBXWARE}\""; \
-	echo "elif [ -f \"\$$HOME/.dbxrc\" ]"; \
-	echo "then"; \
-	echo "	source \"\$$HOME/.dbxrc\""; \
-	echo "fi"; \
-	) > $@
-
-# Skip the test for product builds (which only work when installed in a JDK), to
-# avoid exiting with an error and causing make to halt.
-NO_TEST_MSG	= \
-	echo "$@:  skipping the test--this build must be tested in a JDK."
-
-NO_JAVA_HOME_MSG	= \
-	echo "JAVA_HOME must be set to run this test."
-
-DATA_MODE = $(DATA_MODE/$(BUILDARCH))
-JAVA_FLAG = $(JAVA_FLAG/$(DATA_MODE))
-
-DATA_MODE/i486    = 32
-DATA_MODE/sparc   = 32
-DATA_MODE/sparcv9 = 64
-DATA_MODE/amd64   = 64
-DATA_MODE/ia64    = 64
-DATA_MODE/zero    = $(ARCH_DATA_MODEL)
-
-JAVA_FLAG/32 = -d32
-JAVA_FLAG/64 = -d64
-
-WRONG_DATA_MODE_MSG = \
-	echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK."
-
-CROSS_COMPILING_MSG = \
-	echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run."
-
-test_gamma:  $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "#!/bin/sh"; \
-	echo ""; \
-	$(BUILDTREE_COMMENT); \
-	echo ""; \
-	echo "# Include environment settings for gamma run"; \
-	echo ""; \
-	echo ". ./env.sh"; \
-	echo ""; \
-	echo "# Do not run gamma test for cross compiles"; \
-	echo ""; \
-	echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \
-	echo "  $(CROSS_COMPILING_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Make sure JAVA_HOME is set as it is required for gamma"; \
-	echo ""; \
-	echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \
-	echo "  $(NO_JAVA_HOME_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Check JAVA_HOME version to be used for the test"; \
-	echo ""; \
-	echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \
-	echo "if [ \$$? -ne 0 ]; then "; \
-	echo "  $(WRONG_DATA_MODE_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "GAMMA_PROG=gamma"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  # Ensure architecture for gamma and JAVA_HOME is the same."; \
-	echo "  # NOTE: gamma assumes the OpenJDK directory layout."; \
-	echo ""; \
-	echo "  GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \
-	echo "  JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  if [ ! -f \$${JVM_LIB} ]; then"; \
-	echo "    JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  fi"; \
-	echo "  if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \
-	echo "    $(WRONG_DATA_MODE_MSG)"; \
-	echo "    exit 0"; \
-	echo "  fi"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Compile Queens program for test"; \
-	echo ""; \
-	echo "rm -f Queens.class"; \
-	echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \
-	echo ""; \
-	echo "# Set library path solely for gamma launcher test run"; \
-	echo ""; \
-	echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "export LD_LIBRARY_PATH"; \
-	echo "unset LD_LIBRARY_PATH_32"; \
-	echo "unset LD_LIBRARY_PATH_64"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "  export DYLD_LIBRARY_PATH"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Use the gamma launcher and JAVA_HOME to run the test"; \
-	echo ""; \
-	echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \
-	) > $@
-	$(QUIETLY) chmod +x $@
-
 FORCE:
 
 .PHONY:  all FORCE
--- a/make/linux/makefiles/compiler1.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/compiler1.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
\ No newline at end of file
--- a/make/linux/makefiles/compiler2.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/compiler2.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/linux/makefiles/gcc.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/gcc.make	Mon Apr 15 08:51:19 2013 +0200
@@ -126,17 +126,15 @@
 # Compiler warnings are treated as errors
 WARNINGS_ARE_ERRORS = -Werror
 
-# Except for a few acceptable ones
+WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function
+
 # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit
-# conversions which might affect the values. To avoid that, we need to turn
-# it off explicitly. 
-ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
-ACCEPTABLE_WARNINGS = -Wpointer-arith -Wsign-compare
-else
-ACCEPTABLE_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare
+# conversions which might affect the values. Only enable it in earlier versions.
+ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+WARNING_FLAGS += -Wconversion
 endif
 
-CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ACCEPTABLE_WARNINGS)
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
 # Special cases
 CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) 
 
--- a/make/linux/makefiles/mapfile-vers-debug	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/mapfile-vers-debug	Mon Apr 15 08:51:19 2013 +0200
@@ -131,6 +131,7 @@
                 JVM_GetEnclosingMethodInfo;
                 JVM_GetFieldAnnotations;
                 JVM_GetFieldIxModifiers;
+                JVM_GetFieldTypeAnnotations;
                 JVM_GetHostName;
                 JVM_GetInheritedAccessControlContext;
                 JVM_GetInterfaceVersion;
@@ -152,6 +153,7 @@
                 JVM_GetMethodIxSignatureUTF;
                 JVM_GetMethodParameterAnnotations;
                 JVM_GetMethodParameters;
+                JVM_GetMethodTypeAnnotations;
                 JVM_GetPrimitiveArrayElement;
                 JVM_GetProtectionDomain;
                 JVM_GetSockName;
--- a/make/linux/makefiles/mapfile-vers-product	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/mapfile-vers-product	Mon Apr 15 08:51:19 2013 +0200
@@ -131,6 +131,7 @@
                 JVM_GetEnclosingMethodInfo;
                 JVM_GetFieldAnnotations;
                 JVM_GetFieldIxModifiers;
+                JVM_GetFieldTypeAnnotations;
                 JVM_GetHostName;
                 JVM_GetInheritedAccessControlContext;
                 JVM_GetInterfaceVersion;
@@ -152,6 +153,7 @@
                 JVM_GetMethodIxSignatureUTF;
                 JVM_GetMethodParameterAnnotations;
                 JVM_GetMethodParameters;
+                JVM_GetMethodTypeAnnotations;
                 JVM_GetPrimitiveArrayElement;
                 JVM_GetProtectionDomain;
                 JVM_GetSockName;
--- a/make/linux/makefiles/tiered.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/linux/makefiles/tiered.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/solaris/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/Makefile	Mon Apr 15 08:51:19 2013 +0200
@@ -238,36 +238,24 @@
 
 $(TARGETS_C2):  $(SUBDIRS_C2)
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_TIERED):  $(SUBDIRS_TIERED)
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_C1):  $(SUBDIRS_C1)
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
 $(TARGETS_CORE):  $(SUBDIRS_CORE)
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && ./test_gamma
-endif
 ifdef INSTALL
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
 endif
--- a/make/solaris/build.sh	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-#! /bin/sh
-#
-# Copyright (c) 1998, 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.
-#  
-#
-
-# Make sure the variable JAVA_HOME is set before running this script.
-
-set -u
-
-
-usage() {
-    (
-        echo "Usage : $0 [-sb | -sbfast] config ws_path"
-        echo ""
-        echo "Where:"
-        echo "    -sb     ::= enable source browser info generation for"
-        echo "                all configs during compilation"
-        echo ""
-        echo "    -sbfast ::= enable source browser info generation for"
-        echo "                all configs without compilation"
-        echo ""
-        echo "    config  ::= debug     | debug1     | debugcore"
-        echo "                fastdebug | fastdebug1 | fastdebugcore"
-        echo "                jvmg      | jvmg1      | jvmgcore"
-        echo "                optimized | optimized1 | optimizedcore"
-        echo "                profiled  | profiled1  | profiledcore"
-        echo "                product   | product1   | productcore"
-        echo ""
-        echo "    ws_path ::= path to HotSpot workspace"
-    ) >&2
-    exit 1
-}
-
-# extract possible options
-options=""
-if [ $# -gt 2 ]; then 
-    case "$1" in
-    -sb)
-	options="CFLAGS_BROWSE=-xsb"
-	shift
-	;;
-    -sbfast)
-	options="CFLAGS_BROWSE=-xsbfast"
-	shift
-	;;
-    *)
-	echo "Unknown option: '$1'" >&2
-	usage
-	;;
-    esac
-fi
-
-# should be just two args left at this point
-if [ $# != 2 ]; then 
-    usage
-fi
-
-# Just in case:
-case ${JAVA_HOME} in
-/*) true;;
-?*) JAVA_HOME=`( cd $JAVA_HOME; pwd )`;;
-esac
-
-if [ "${JAVA_HOME}" = ""  -o  ! -d "${JAVA_HOME}" -o ! -d ${JAVA_HOME}/jre/lib/`uname -p` ]; then
-    echo "JAVA_HOME needs to be set to a valid JDK path"
-    echo "ksh : export JAVA_HOME=/net/tetrasparc/export/gobi/JDK1.2_fcs_V/solaris"
-    echo "csh : setenv JAVA_HOME /net/tetrasparc/export/gobi/JDK1.2_fcs_V/solaris"
-    exit 1
-fi
-
-
-LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/`uname -p`:\
-${JAVA_HOME}/jre/lib/`uname -p`/native_threads:${LD_LIBRARY_PATH-.}
-
-# This is necessary as long as we are using the old launcher
-# with the new distribution format:
-CLASSPATH=${JAVA_HOME}/jre/lib/rt.jar:${CLASSPATH-.}
-
-
-for gm in gmake gnumake
-do
-  if [ "${GNUMAKE-}" != "" ]; then break; fi
-  ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm
-done
-: ${GNUMAKE:?'Cannot locate the gnumake program.  Stop.'}
-
-
-echo "### ENVIRONMENT SETTINGS:"
-export JAVA_HOME		; echo "JAVA_HOME=$JAVA_HOME"
-export LD_LIBRARY_PATH		; echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
-export CLASSPATH		; echo "CLASSPATH=$CLASSPATH"
-export GNUMAKE			; echo "GNUMAKE=$GNUMAKE"
-echo "###"
-
-config=$1
-ws_path=$2
-
-case ${ws_path} in
-/*) true;;
-?*) ws_path=`(cd ${ws_path}; pwd)`;;
-esac
-
-echo \
-${GNUMAKE} -f ${ws_path}/make/solaris/Makefile \
-    $config GAMMADIR=${ws_path} $options
-${GNUMAKE} -f ${ws_path}/make/solaris/Makefile \
-    $config GAMMADIR=${ws_path} $options
--- a/make/solaris/makefiles/buildtree.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/buildtree.make	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -50,21 +50,19 @@
 # jvmti.make	- generate JVMTI bindings from the spec (JSR-163)
 # sa.make	- generate SA jar file and natives
 # env.[ck]sh	- environment settings
-# test_gamma	- script to run the Queens program
 # 
 # The makefiles are split this way so that "make foo" will run faster by not
 # having to read the dependency files for the vm.
 
 -include $(SPEC)
 include $(GAMMADIR)/make/scm.make
+include $(GAMMADIR)/make/defs.make
 include $(GAMMADIR)/make/altsrc.make
 
+
 # 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details.
 QUIETLY$(MAKE_VERBOSE)	= @
 
-# For now, until the compiler is less wobbly:
-TESTFLAGS	= -Xbatch -Xmx32m -showversion
-
 ### maye ARCH_XXX instead?
 ifdef USE_GCC
 PLATFORM_FILE	= $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).gcc
@@ -119,7 +117,7 @@
 BUILDTREE_MAKE	= $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
 
 BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \
-        env.sh env.csh jdkpath.sh .dbxrc test_gamma
+        env.sh env.csh jdkpath.sh
 
 BUILDTREE_VARS	= GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
 	ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
@@ -178,6 +176,19 @@
 # literal "$(GAMMADIR)/" suitable for inclusion in a Makefile.  
 gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2)))
 
+# This bit is needed to enable local rebuilds.
+# Unless the makefile itself sets LP64, any environmental
+# setting of LP64 will interfere with the build.
+LP64_SETTING/32 = LP64 = \#empty
+LP64_SETTING/64 = LP64 = 1
+
+DATA_MODE/i486 = 32
+DATA_MODE/sparc = 32
+DATA_MODE/sparcv9 = 64
+DATA_MODE/amd64 = 64
+
+DATA_MODE = $(DATA_MODE/$(BUILDARCH))
+
 flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
@@ -334,7 +345,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
+	{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
 	{ \
 	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; \
@@ -346,8 +357,7 @@
 	@echo Creating $@ ...
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
-	[ -n "$$JAVA_HOME" ] && \
-	{ echo "if (! \$$?JAVA_HOME) setenv JAVA_HOME \"$$JAVA_HOME\""; }; \
+	{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
 	sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
 	) > $@
 
@@ -358,124 +368,6 @@
 	echo "JDK=${JAVA_HOME}"; \
 	) > $@	   
 
-.dbxrc:  $(BUILDTREE_MAKE)
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "echo '# Loading $(PLATFORM_DIR)/$(TARGET)/.dbxrc'"; \
-	echo "if [ -f \"\$${HOTSPOT_DBXWARE}\" ]"; \
-	echo "then"; \
-	echo "	source \"\$${HOTSPOT_DBXWARE}\""; \
-	echo "elif [ -f \"\$$HOME/.dbxrc\" ]"; \
-	echo "then"; \
-	echo "	source \"\$$HOME/.dbxrc\""; \
-	echo "fi"; \
-	) > $@
-
-# Skip the test for product builds (which only work when installed in a JDK), to
-# avoid exiting with an error and causing make to halt.
-NO_TEST_MSG	= \
-	echo "$@:  skipping the test--this build must be tested in a JDK."
-
-NO_JAVA_HOME_MSG	= \
-	echo "JAVA_HOME must be set to run this test."
-
-DATA_MODE = $(DATA_MODE/$(BUILDARCH))
-JAVA_FLAG = $(JAVA_FLAG/$(DATA_MODE))
-
-DATA_MODE/i486    = 32
-DATA_MODE/sparc   = 32
-DATA_MODE/sparcv9 = 64
-DATA_MODE/amd64   = 64
-DATA_MODE/ia64    = 64
-
-# This bit is needed to enable local rebuilds.
-# Unless the makefile itself sets LP64, any environmental
-# setting of LP64 will interfere with the build.
-LP64_SETTING/32 = LP64 = \#empty
-LP64_SETTING/64 = LP64 = 1
-
-JAVA_FLAG/32 = -d32
-JAVA_FLAG/64 = -d64
-
-WRONG_DATA_MODE_MSG = \
-	echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK."
-
-CROSS_COMPILING_MSG = \
-	echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run."
-
-test_gamma:  $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java
-	@echo Creating $@ ...
-	$(QUIETLY) ( \
-	echo "#!/bin/sh"; \
-	echo ""; \
-	$(BUILDTREE_COMMENT); \
-	echo ""; \
-	echo "# Include environment settings for gamma run"; \
-	echo ""; \
-	echo ". ./env.sh"; \
-	echo ""; \
-	echo "# Do not run gamma test for cross compiles"; \
-	echo ""; \
-	echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \
-	echo "  $(CROSS_COMPILING_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Make sure JAVA_HOME is set as it is required for gamma"; \
-	echo ""; \
-	echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \
-	echo "  $(NO_JAVA_HOME_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Check JAVA_HOME version to be used for the test"; \
-	echo ""; \
-	echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \
-	echo "if [ \$$? -ne 0 ]; then "; \
-	echo "  $(WRONG_DATA_MODE_MSG)"; \
-	echo "  exit 0"; \
-	echo "fi"; \
-	echo ""; \
-	echo "GAMMA_PROG=gamma"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  # Ensure architecture for gamma and JAVA_HOME is the same."; \
-	echo "  # NOTE: gamma assumes the OpenJDK directory layout."; \
-	echo ""; \
-	echo "  GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \
-	echo "  JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  if [ ! -f \$${JVM_LIB} ]; then"; \
-	echo "    JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \
-	echo "  fi"; \
-	echo "  if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \
-	echo "    $(WRONG_DATA_MODE_MSG)"; \
-	echo "    exit 0"; \
-	echo "  fi"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Compile Queens program for test"; \
-	echo ""; \
-	echo "rm -f Queens.class"; \
-	echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \
-	echo ""; \
-	echo "# Set library path solely for gamma launcher test run"; \
-	echo ""; \
-	echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "export LD_LIBRARY_PATH"; \
-	echo "unset LD_LIBRARY_PATH_32"; \
-	echo "unset LD_LIBRARY_PATH_64"; \
-	echo ""; \
-	echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \
-	echo "  DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
-	echo "  export DYLD_LIBRARY_PATH"; \
-	echo "fi"; \
-	echo ""; \
-	echo "# Use the gamma launcher and JAVA_HOME to run the test"; \
-	echo ""; \
-	echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \
-	) > $@
-	$(QUIETLY) chmod +x $@
-
 FORCE:
 
 .PHONY:  all FORCE
--- a/make/solaris/makefiles/compiler1.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/compiler1.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
--- a/make/solaris/makefiles/compiler2.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/compiler2.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/solaris/makefiles/gcc.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/gcc.make	Mon Apr 15 08:51:19 2013 +0200
@@ -118,8 +118,8 @@
 # Compiler warnings are treated as errors 
 WARNINGS_ARE_ERRORS = -Werror 
 # Enable these warnings. See 'info gcc' about details on these options
-ADDITIONAL_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare 
-CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ADDITIONAL_WARNINGS) 
+WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
 # Special cases 
 CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))  
 
--- a/make/solaris/makefiles/mapfile-vers	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/mapfile-vers	Mon Apr 15 08:51:19 2013 +0200
@@ -131,6 +131,7 @@
                 JVM_GetEnclosingMethodInfo;
                 JVM_GetFieldAnnotations;
                 JVM_GetFieldIxModifiers;
+                JVM_GetFieldTypeAnnotations;
                 JVM_GetHostName;
                 JVM_GetInheritedAccessControlContext;
                 JVM_GetInterfaceVersion;
@@ -152,6 +153,7 @@
                 JVM_GetMethodIxSignatureUTF;
                 JVM_GetMethodParameterAnnotations;
                 JVM_GetMethodParameters;
+                JVM_GetMethodTypeAnnotations;
                 JVM_GetPrimitiveArrayElement;
                 JVM_GetProtectionDomain;
                 JVM_GetSockName;
--- a/make/solaris/makefiles/tiered.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/solaris/makefiles/tiered.make	Mon Apr 15 08:51:19 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/test/Queens.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2006, 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.
- *
- */
-
-import java.util.*;
-
-// Copyright 1996, Animorphic Systems
-// gri 28 Aug 92 / 15 Jan 93 / 8 Dec 95
-
-class Queens {
-
-  static void try_i(boolean a[], boolean b[], boolean c[], int x[], int i) {
-    int adj = 7;
-
-    for (int j = 1; j <= 8; j++) {
-      if (b[j] && a[i+j] && c[adj+i-j]) {
-        x[i] = j;
-        b[j] = false;
-        a[i+j] = false;
-        c[adj+i-j] = false;
-        if (i < 8) try_i(a, b, c, x, i+1);
-        else print(x);
-        b[j] = true;
-        a[i+j] = true;
-        c[adj+i-j] = true;
-      }
-    }
-  }
-
-  public static void main(String s[]) {
-    boolean a[] = new boolean[16+1];
-    boolean b[] = new boolean[ 8+1];
-    boolean c[] = new boolean[14+1];
-    int     x[] = new int[8+1];
-    int adj = 7;
-
-    for (int i = -7; i <= 16; i++) {
-      if (i >= 1 && i <= 8) b[i]     = true;
-      if (i >= 2)           a[i]     = true;
-      if (i <= 7)           c[adj+i] = true;
-    }
-
-    x[0] = 0; // solution counter
-
-    try_i(a, b, c, x, 1);
-  }
-
-  static void print(int x[]) {
-    // first correct solution: A1 B5 C8 D6 E3 F7 G2 H4
-
-    char LF = (char)0xA;
-    char CR = (char)0xD;
-
-    x[0]++;
-    if (x[0] < 10)
-        System.out.print(" ");
-    System.out.print(x[0] + ". ");
-    for (int i = 1; i <= 8; i++) {
-      char p = (char)('A' + i - 1);
-      System.out.print(p);
-      System.out.print (x[i] + " ");
-    }
-    System.out.println();
-  }
-
-};
--- a/make/windows/build.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/windows/build.make	Mon Apr 15 08:51:19 2013 +0200
@@ -110,8 +110,6 @@
 !endif
 !elseif "$(Variant)" == "tiered"
 VARIANT_TEXT=Tiered
-!elseif "$(Variant)" == "kernel"
-VARIANT_TEXT=Kernel
 !elseif "$(Variant)" == "graal"
 VARIANT_TEXT=Graal
 !endif
@@ -307,9 +305,9 @@
 checks: checkVariant checkWorkSpace checkSA
 
 checkVariant:
-	@ if "$(Variant)"=="" echo Need to specify "Variant=[graal|tiered|compiler2|compiler1|kernel|core]" && false
-	@ if "$(Variant)" NEQ "graal" if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "kernel" if "$(Variant)" NEQ "core" \
-          echo Need to specify "Variant=[graal|tiered|compiler2|compiler1|kernel|core]" && false
+	@ if "$(Variant)"=="" echo Need to specify "Variant=[graal|tiered|compiler2|compiler1|core]" && false
+	@ if "$(Variant)" NEQ "graal" if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "core" \
+          echo Need to specify "Variant=[graal|tiered|compiler2|compiler1|core]" && false
 
 checkWorkSpace:
 	@ if "$(WorkSpace)"=="" echo Need to specify "WorkSpace=..." && false
--- a/make/windows/create.bat	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/windows/create.bat	Mon Apr 15 08:51:19 2013 +0200
@@ -37,10 +37,14 @@
 REM that "grep" be accessible on the PATH. An MKS install does this.
 REM 
 
-rem cl 2>NUL >NUL
-rem if %errorlevel% == 0 goto nexttest
-rem echo Make sure cl.exe is in your PATH before running this script.
-rem goto end
+
+
+REM (cwirth) does not return a proper error code, so build fails all the time
+REM
+REM cl 2>NUL >NUL
+REM if %errorlevel% == 0 goto nexttest
+REM echo Make sure cl.exe is in your PATH before running this script.
+REM goto end
 
 :nexttest
 grep -V 2>NUL >NUL
@@ -52,8 +56,6 @@
 :testit
 cl 2>&1 | grep "x64" >NUL
 if %errorlevel% == 0 goto amd64
-cl 2>&1 | grep "x64" >NUL
-if %errorlevel% == 0 goto amd64
 set ARCH=x86
 set BUILDARCH=i486
 set Platform_arch=x86
@@ -150,7 +152,7 @@
 
 REM This is now safe to do.
 :copyfiles
-for /D %%i in (graal, compiler1, compiler2, tiered, core, kernel) do (
+for /D %%i in (graal, compiler1, compiler2, tiered, core) do (
 if NOT EXIST %HotSpotBuildSpace%\%%i\generated mkdir %HotSpotBuildSpace%\%%i\generated
 copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\generated > NUL
 )
@@ -158,7 +160,7 @@
 REM force regneration of ProjectFile
 if exist %ProjectFile% del %ProjectFile%
 
-for /D %%i in (graal, compiler1, compiler2, tiered, core, kernel) do (
+for /D %%i in (graal, compiler1, compiler2, tiered, core) do (
 echo -- %%i --
 echo # Generated file!                                                        >    %HotSpotBuildSpace%\%%i\local.make
 echo # Changing a variable below and then deleting %ProjectFile% will cause  >>    %HotSpotBuildSpace%\%%i\local.make
--- a/make/windows/makefiles/compile.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/windows/makefiles/compile.make	Mon Apr 15 08:51:19 2013 +0200
@@ -221,13 +221,6 @@
 !endif
 !endif
 
-# Compile for space above time.
-!if "$(Variant)" == "kernel"
-PRODUCT_OPT_OPTION   = /O1 /Oy-
-FASTDEBUG_OPT_OPTION = /O1 /Oy-
-DEBUG_OPT_OPTION     = /Od
-!endif
-
 # If NO_OPTIMIZATIONS is defined in the environment, turn everything off
 !ifdef NO_OPTIMIZATIONS
 PRODUCT_OPT_OPTION   = $(DEBUG_OPT_OPTION)
--- a/make/windows/makefiles/product.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/windows/makefiles/product.make	Mon Apr 15 08:51:19 2013 +0200
@@ -51,13 +51,6 @@
 # Force resources to be rebuilt every time
 $(Res_Files): FORCE
 
-# Kernel doesn't need exported vtbl symbols.
-!if "$(Variant)" == "kernel"
-$(AOUT): $(Res_Files) $(Obj_Files)
-	$(LD) @<<
-  $(LD_FLAGS) /out:$@ /implib:$*.lib $(Obj_Files) $(Res_Files)
-<<
-!else
 vm.def: $(Obj_Files)
 	sh $(WorkSpace)/make/windows/build_vm_def.sh
 
@@ -65,7 +58,6 @@
 	$(LD) @<<
   $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
 <<
-!endif
 !if "$(MT)" != ""
 # The previous link command created a .manifest file that we want to
 # insert into the linked artifact so we do not need to track it
--- a/make/windows/makefiles/vm.make	Thu Apr 04 11:57:04 2013 +0200
+++ b/make/windows/makefiles/vm.make	Mon Apr 15 08:51:19 2013 +0200
@@ -93,12 +93,8 @@
 # AsyncGetCallTrace is not supported on IA64 yet
 AGCT_EXPORT=
 !else
-!if "$(Variant)" == "kernel"
-AGCT_EXPORT=
-!else
 AGCT_EXPORT=/export:AsyncGetCallTrace
 !endif
-!endif
 
 # If you modify exports below please do the corresponding changes in
 # src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
--- a/make/windows/projectfiles/kernel/Makefile	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#
-# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# 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 ../local.make
-
-!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
--- a/make/windows/projectfiles/kernel/vm.def	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-;
-; This .DEF file is a placeholder for one which is automatically
-; generated during the build process. See
-; make\windows\build_vm_def.sh and
-; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
-; options).
-;
--- a/make/windows/projectfiles/kernel/vm.dsw	Thu Apr 04 11:57:04 2013 +0200
+++ /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: "vm"=.\vm.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
--- a/mx/commands.py	Thu Apr 04 11:57:04 2013 +0200
+++ b/mx/commands.py	Mon Apr 15 08:51:19 2013 +0200
@@ -38,13 +38,19 @@
 """ Used to distinguish an exported GraalVM (see 'mx export'). """
 _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src'))
 
-""" The VM that will be run by the 'vm' command: graal(default), client or server.
+""" The VMs that can be built and run - default is first in list """
+_vmChoices = ['graal', 'server', 'client', 'server-nograal', 'client-nograal', 'boot']
+
+""" The VM that will be run by the 'vm' command and built by default by the 'build' command.
     This can be set via the global '--vm' option. """
-_vm = 'graal'
+_vm = _vmChoices[0]
 
-""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug.
-    This can be set via the global '--fastdebug' and '--debug' options. """
-_vmbuild = 'product'
+""" The VM builds that will be run by the 'vm' command - default is first in list """
+_vmbuildChoices = ['product', 'fastdebug', 'debug']
+
+""" The VM build that will be run by the 'vm' command.
+    This can be set via the global '--product', '--fastdebug' and '--debug' options. """
+_vmbuild = _vmbuildChoices[0]
 
 _jacoco = 'off'
 
@@ -66,11 +72,16 @@
     """clean the GraalVM source tree"""
     opts = mx.clean(args, parser=ArgumentParser(prog='mx clean'))
     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' + str(mx.java().version))
-        if exists(jdks):
-            shutil.rmtree(jdks)
+        def rmIfExists(name):
+            if os.path.isdir(name):
+                shutil.rmtree(name)
+            elif os.path.isfile(name):
+                os.unlink(name)
+                
+        rmIfExists(join(_graal_home, 'build'))
+        rmIfExists(join(_graal_home, 'build-nograal'))
+        rmIfExists(join(_graal_home, 'jdk' + str(mx.java().version)))
+        rmIfExists(mx.distribution('GRAAL').path)
 
 def export(args):
     """create a GraalVM zip file for distribution"""
@@ -296,14 +307,14 @@
     Get the JDK into which Graal is installed, creating it first if necessary.
     """
     jdk = join(_graal_home, 'jdk' + str(mx.java().version), build)
+    srcJdk = mx.java().jdk
     jdkContents = ['bin', 'include', 'jre', 'lib']
-    if (exists(join(jdk, 'db'))):
+    if exists(join(srcJdk, 'db')):
         jdkContents.append('db')
-    if mx.get_os() != 'windows':
+    if mx.get_os() != 'windows' and exists(join(srcJdk, 'man')):
         jdkContents.append('man')
     if create:
         if not exists(jdk):
-            srcJdk = mx.java().jdk
             mx.log('Creating ' + jdk + ' from ' + srcJdk)
             os.makedirs(jdk)
             for d in jdkContents:
@@ -320,6 +331,7 @@
                 mx.abort(jvmCfg + ' does not exist')
 
             defaultVM = None
+            jvmCfgLines = []
             with open(jvmCfg) as f:
                 for line in f:
                     if line.startswith('-') and defaultVM is None:
@@ -327,14 +339,20 @@
                         assert len(parts) == 2, parts
                         assert parts[1] == 'KNOWN', parts[1]
                         defaultVM = parts[0][1:]
+                        jvmCfgLines += ['# boot VM is a copy of the unmodified ' + defaultVM + ' VM\n']
+                        jvmCfgLines += ['-boot KNOWN\n']
+                    else:
+                        jvmCfgLines += [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'))
+            shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'boot'))
+            
 
             with open(jvmCfg, 'w') as fp:
-                print >> fp, '-' + defaultVM + '0 KNOWN'
+                for line in jvmCfgLines:
+                    fp.write(line)
 
             # Install a copy of the disassembler library
             try:
@@ -479,7 +497,7 @@
     
     out.element('target', {'name' : 'main', 'depends' : 'jar'})
 
-    out.open('target', {'name' : 'compile'})
+    out.open('target', {'name' : 'compile', 'depends' : 'cleanclasses'})
     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):
@@ -500,9 +518,12 @@
     out.element('jar', {'destfile' : '${jar.file}', 'basedir' : '${classes.dir}'})
     out.close('target')
     
-    out.open('target', {'name' : 'clean'})
+    out.open('target', {'name' : 'cleanclasses'})
     out.element('delete', {'dir' : '${classes.dir}'})
-    out.element('delete', {'file' : '${jar.filr}'})
+    out.close('target')
+
+    out.open('target', {'name' : 'clean', 'depends' : 'cleanclasses'})
+    out.element('delete', {'file' : '${jar.file}'})
     out.close('target')
 
     out.close('project')
@@ -530,9 +551,9 @@
     if vm is None:
         vm = _vm
 
-    if vm == 'server':
+    if vm.startswith('server') or vm == 'boot':
         buildSuffix = ''
-    elif vm == 'client':
+    elif vm.startswith('client'):
         buildSuffix = '1'
     else:
         assert vm == 'graal', vm
@@ -549,6 +570,11 @@
 
         jdk = _jdk(build, create=True)
 
+        if vm == 'boot':
+            if build != 'product':
+                mx.log('only product build of boot VM exists')
+            continue
+
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
             if mx.get_os() != 'windows':
@@ -606,12 +632,16 @@
             if build == 'debug':
                 build = 'jvmg'
             runCmd.append(build + buildSuffix) 
-            env = os.environ
+            env = os.environ.copy()
             env.setdefault('ARCH_DATA_MODEL', '64')
             env.setdefault('LANG', 'C')
             env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
-            env['ALT_BOOTDIR'] = jdk
-            if not env.has_key('OMIT_GRAAL'):
+            env['ALT_BOOTDIR'] = mx.java().jdk
+            env['JAVA_HOME'] = jdk
+            if vm.endswith('nograal'):
+                env['OMIT_GRAAL'] = 'true'
+                env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os()))
+            else:
                 env['GRAAL'] = join(_graal_home, 'graal') # needed for TEST_IN_BUILD
             env.setdefault('INSTALL', 'y')
             if mx.get_os() == 'solaris' :
@@ -636,26 +666,34 @@
             env.pop('LD_LIBRARY_PATH', None)
             env.pop('CLASSPATH', None)
 
-            mx.run(runCmd, cwd=join(_graal_home, 'make'), err=filterXusage)
+            mx.run(runCmd, cwd=join(_graal_home, 'make'), err=filterXusage, env=env)
 
         jvmCfg = _vmCfgInJdk(jdk)
-        found = False
         if not exists(jvmCfg):
             mx.abort(jvmCfg + ' does not exist')
 
-        prefix = '-' + vm
-        vmKnown = prefix + ' KNOWN'
+        prefix = '-' + vm + ' '
+        vmKnown = prefix + 'KNOWN\n'
+        lines = []
+        found = False
         with open(jvmCfg) as f:
             for line in f:
-                if vmKnown == line.strip():
+                if line.strip() == vmKnown.strip():
                     found = True
-                    break
+                lines.append(line)
+                
         if not found:
-            mx.log('Appending "' + prefix + ' KNOWN" to ' + jvmCfg)
+            mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
                 os.chmod(jvmCfg, 0755)
-            with open(jvmCfg, 'a') as f:
-                print >> f, vmKnown
+            with open(jvmCfg, 'w') as f:
+                for line in lines:
+                    if line.startswith(prefix):
+                        line = vmKnown
+                        found = True
+                    f.write(line)
+                if not found:
+                    f.write(vmKnown)
 
         if exists(timestampFile):
             os.utime(timestampFile, None)
@@ -753,12 +791,14 @@
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
     javaClass = join(mxdir, name + '.class')
-    (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
+    testfile = os.environ.get('MX_TESTFILE', None)
+    if testfile is None:
+        (_, 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])
-        if _vm == 'server0':
+        if _vm == 'boot' or _vm.endswith('nograal'):
             prefixArgs = ['-esa', '-ea']
         else:
             prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
@@ -767,7 +807,8 @@
     try:
         _run_tests(args, harness, annotations, testfile)
     finally:
-        os.remove(testfile)
+        if os.environ.get('MX_TESTFILE') is None:
+            os.remove(testfile)
 
 def unittest(args):
     """run the JUnit tests (all testcases)
@@ -799,9 +840,14 @@
 def buildvms(args):
     """build one or more VMs in various configurations"""
 
+    vmsDefault = ','.join(_vmChoices)
+    vmbuildsDefault = ','.join(_vmbuildChoices)
+    
     parser = ArgumentParser(prog='mx buildvms');
-    parser.add_argument('--vms', help='a comma separated list of VMs to build (default: server,client,graal)', default='server,client,graal')
-    parser.add_argument('--builds', help='a comma separated list of build types (default: product,fastdebug,debug)', default='product,fastdebug,debug')
+    parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
+    parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
+    parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
+    parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file')
 
     args = parser.parse_args(args)
     vms = args.vms.split(',')
@@ -810,14 +856,26 @@
     allStart = time.time()
     for v in vms:
         for vmbuild in builds:
-            logFile = join(v + '-' + vmbuild + '.log')
-            log = open(join(_graal_home, logFile), 'wb')
-            start = time.time()
-            mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
-            # Run as subprocess so that output can be directed to a file
-            subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
-            duration = datetime.timedelta(seconds=time.time() - start)
-            mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
+            if v == 'boot' and vmbuild != 'product':
+                continue
+            if not args.console:
+                logFile = join(v + '-' + vmbuild + '.log')
+                log = open(join(_graal_home, logFile), 'wb')
+                start = time.time()
+                mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
+                # Run as subprocess so that output can be directed to a file
+                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
+                duration = datetime.timedelta(seconds=time.time() - start)
+                mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
+            else:
+                global _vm
+                _vm = v
+                build([vmbuild])
+            if not args.no_check:
+                vmargs = ['-version']
+                if v == 'graal':
+                    vmargs.insert(0, '-XX:-BootstrapGraal')
+                vm(vmargs, vm=v, vmbuild=vmbuild)
     allDuration = datetime.timedelta(seconds=time.time() - allStart)
     mx.log('TOTAL TIME:   ' + '[' + str(allDuration) + ']')
 
@@ -1042,7 +1100,9 @@
         for dacapo in dacapos:
             if dacapo not in sanitycheck.dacapoSanityWarmup.keys():
                 mx.abort('Unknown DaCapo : ' + dacapo)
-            benchmarks += [sanitycheck.getDacapo(dacapo, sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark])]
+            iterations = sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark]
+            if (iterations > 0):
+                benchmarks += [sanitycheck.getDacapo(dacapo, iterations)]
 
     if ('scaladacapo' in args or 'all' in args):
         benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
@@ -1051,7 +1111,9 @@
         for scaladacapo in scaladacapos:
             if scaladacapo not in sanitycheck.dacapoScalaSanityWarmup.keys():
                 mx.abort('Unknown Scala DaCapo : ' + scaladacapo)
-            benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, sanitycheck.dacapoScalaSanityWarmup[scaladacapo][sanitycheck.SanityCheckLevel.Benchmark])]
+            iterations = sanitycheck.dacapoScalaSanityWarmup[scaladacapo][sanitycheck.SanityCheckLevel.Benchmark]
+            if (iterations > 0):
+                benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, iterations)]
 
     #Bootstrap
     if ('bootstrap' in args or 'all' in args):
@@ -1261,18 +1323,16 @@
     mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
 
     if (_vmSourcesAvailable):
-        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client', 'server0'], help='the VM to build/run (default: graal)')
-        mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM')
-        mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM')
-        mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM')
+        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')')
+        for c in _vmbuildChoices:
+            mx.add_argument('--' + c, action='store_const', dest='vmbuild', const=c, help='select the ' + c + ' build of the VM')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
         mx.add_argument('--native-dbg', action='store', dest='native_dbg', help='Start the vm inside a debugger', metavar='<debugger>')
         mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='native_dbg', help='alias for --native-dbg /usr/bin/gdb -- args')
-        
 
         commands.update({
             'export': [export, '[-options] [zipfile]'],
-            'build': [build, '[-options] [product|debug|fastdebug]...']
+            'build': [build, '[-options] [' + '|'.join(_vmbuildChoices) + ']...']
         })
 
     mx.commands.update(commands)
--- a/mx/projects	Thu Apr 04 11:57:04 2013 +0200
+++ b/mx/projects	Mon Apr 15 08:51:19 2013 +0200
@@ -125,7 +125,7 @@
 # graal.hotspot.test
 project@com.oracle.graal.hotspot.test@subDir=graal
 project@com.oracle.graal.hotspot.test@sourceDirs=src
-project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
+project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 
@@ -155,6 +155,13 @@
 project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.debug@javaCompliance=1.7
 
+# graal.debug.test
+project@com.oracle.graal.debug.test@subDir=graal
+project@com.oracle.graal.debug.test@sourceDirs=src
+project@com.oracle.graal.debug.test@dependencies=JUNIT,com.oracle.graal.debug
+project@com.oracle.graal.debug.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.debug.test@javaCompliance=1.7
+
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
 project@com.oracle.graal.lir@sourceDirs=src
@@ -215,7 +222,7 @@
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
 project@com.oracle.graal.replacements.test@sourceDirs=src
-project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.replacements,com.oracle.graal.compiler.test
+project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.test@javaCompliance=1.7
 
@@ -229,7 +236,7 @@
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
 project@com.oracle.graal.nodes@sourceDirs=src
-project@com.oracle.graal.nodes@dependencies=com.oracle.graal.api.code,com.oracle.graal.graph,com.oracle.graal.debug
+project@com.oracle.graal.nodes@dependencies=com.oracle.graal.api.code,com.oracle.graal.graph,com.oracle.graal.debug,com.oracle.graal.api.replacements
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.7
 
@@ -243,7 +250,7 @@
 # graal.phases.common
 project@com.oracle.graal.phases.common@subDir=graal
 project@com.oracle.graal.phases.common@sourceDirs=src
-project@com.oracle.graal.phases.common@dependencies=com.oracle.graal.phases,com.oracle.graal.api.replacements
+project@com.oracle.graal.phases.common@dependencies=com.oracle.graal.phases
 project@com.oracle.graal.phases.common@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.phases.common@javaCompliance=1.7
 
@@ -333,7 +340,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 
--- a/mxtool/mx.py	Thu Apr 04 11:57:04 2013 +0200
+++ b/mxtool/mx.py	Mon Apr 15 08:51:19 2013 +0200
@@ -663,12 +663,14 @@
     def element(self, tag, attributes={}, data=None):
         return self.open(tag, attributes, data).close(tag)
 
-    def xml(self, indent='', newl='', escape=False):
+    def xml(self, indent='', newl='', escape=False, standalone=None):
         assert self.current == self
         result = self.toprettyxml(indent, newl, encoding="UTF-8")
         if escape:
             entities = { '"':  "&quot;", "'":  "&apos;", '\n': '&#10;' }
             result = xml.sax.saxutils.escape(result, entities)
+        if standalone is not None:
+            result = result.replace('encoding="UTF-8"?>', 'encoding="UTF-8" standalone="' + str(standalone) + '"?>')
         return result
 
 def get_os():
@@ -944,7 +946,7 @@
         retcode = p.wait()
     return retcode
 
-def run(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None):
+def run(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None):
     """
     Run a command in a subprocess, wait for it to complete and return the exit status of the process.
     If the exit status is non-zero and `nonZeroIsFatal` is true, then mx is exited with
@@ -981,7 +983,7 @@
 
         if not callable(out) and not callable(err) and timeout is None:
             # The preexec_fn=os.setsid
-            p = subprocess.Popen(args, cwd=cwd, preexec_fn=preexec_fn, creationflags=creationflags)
+            p = subprocess.Popen(args, cwd=cwd, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
             _currentSubprocess = (p, args)
             retcode = waitOn(p)
         else:
@@ -991,7 +993,7 @@
                 stream.close()
             stdout=out if not callable(out) else subprocess.PIPE
             stderr=err if not callable(err) else subprocess.PIPE
-            p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags)
+            p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
             _currentSubprocess = (p, args)
             if callable(out):
                 t = Thread(target=redirect, args=(p.stdout, out))
@@ -1342,7 +1344,7 @@
     parser = parser if parser is not None else ArgumentParser(prog='mx build')
     parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)')
     parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output')
-    parser.add_argument('--source', dest='compliance', help='Java compliance level', default=str(javaCompliance))
+    parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one', default=str(javaCompliance))
     parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
     parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)')
     parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
@@ -1500,16 +1502,17 @@
 
         toBeDeleted = [argfileName]
         try:
+            compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name]
+                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name]
                 if not args.warnAPI:
                     javacCmd.append('-XDignore.symbol.file')
                 run(javacCmd)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
                 jdtArgs = [java().java, '-Xmx1g', '-jar', jdtJar,
-                         '-' + args.compliance,
+                         '-' + compliance,
                          '-cp', cp, '-g', '-enableJavadoc',
                          '-d', outputDir] + javacArgs
                 jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs')
@@ -1559,6 +1562,13 @@
         args.eclipse_exe = os.environ.get('ECLIPSE_EXE')
     if args.eclipse_exe is None:
         abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.')
+        
+    # Maybe an Eclipse installation dir was specified - look for the executable in it
+    if join(args.eclipse_exe, exe_suffix('eclipse')):
+        args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse'))
+        
+    if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK):
+        abort('Not an executable file: ' + args.eclipse_exe)
 
     eclipseinit([], buildProcessorJars=False)
 
@@ -1811,11 +1821,6 @@
                 log('[all Java sources in {0} already checked - skipping]'.format(sourceDir))
                 continue
 
-            if exists(timestampFile):
-                os.utime(timestampFile, None)
-            else:
-                file(timestampFile, 'a')
-
             dotCheckstyleXML = xml.dom.minidom.parse(dotCheckstyle)
             localCheckConfig = dotCheckstyleXML.getElementsByTagName('local-check-config')[0]
             configLocation = localCheckConfig.getAttribute('location')
@@ -1881,6 +1886,11 @@
                                 if len(warnings) != 0:
                                     map(log, warnings)
                                     return 1
+                                else:
+                                    if exists(timestampFile):
+                                        os.utime(timestampFile, None)
+                                    else:
+                                        file(timestampFile, 'a')
             finally:
                 if exists(auditfileName):
                     os.unlink(auditfileName)
@@ -1977,16 +1987,16 @@
     slm.open('sourceContainers', {'duplicates' : 'false'})
 
     # Every Java program depends on the JRE
-    memento = XMLDoc().element('classpathContainer', {'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'}).xml()
+    memento = XMLDoc().element('classpathContainer', {'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'}).xml(standalone='no')
     slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'})
 
     for dep in deps:
         if dep.isLibrary():
             if hasattr(dep, 'eclipse.container'):
-                memento = XMLDoc().element('classpathContainer', {'path' : getattr(dep, 'eclipse.container')}).xml()
+                memento = XMLDoc().element('classpathContainer', {'path' : getattr(dep, 'eclipse.container')}).xml(standalone='no')
                 slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'})
         else:
-            memento = XMLDoc().element('javaProject', {'name' : dep.name}).xml()
+            memento = XMLDoc().element('javaProject', {'name' : dep.name}).xml(standalone='no')
             slm.element('container', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.javaProject'})
 
     slm.close('sourceContainers')
@@ -2010,7 +2020,7 @@
     launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.PROJECT_ATTR', 'value' : ''})
     launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_CONNECTOR_ID', 'value' : 'org.eclipse.jdt.launching.socketAttachConnector'})
     launch.close('launchConfiguration')
-    launch = launch.xml(newl='\n') % slm.xml(escape=True)
+    launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no')
 
     if name is None:
         name = 'attach-' + hostname + '-' + port
@@ -2077,7 +2087,7 @@
     launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.PROJECT_ATTR', 'value' : ''})
     launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_ARGUMENTS', 'value' : ' '.join(vmArgs)})
     launch.close('launchConfiguration')
-    launch = launch.xml(newl='\n') % slm.xml(escape=True)
+    launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no')
 
     eclipseLaunches = join('mx', 'eclipse-launches')
     if not exists(eclipseLaunches):
@@ -2214,7 +2224,7 @@
                 out.close('buildCommand')
 
         if _isAnnotationProcessorDependency(p):
-            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False)
+            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False, xmlIndent='', xmlStandalone='no')
             _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh = True, async = True)
                        
         if projToDist.has_key(p.name):
@@ -2296,10 +2306,11 @@
     
     return False
 
-def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False):
+def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None):
     launchOut = XMLDoc();
     consoleOn = 'true' if logToConsole else 'false'
     launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output',                'value': consoleOn})
     launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
     launchOut.element('mapEntry', {'key' : 'JAVA_HOME',	'value' : java().jdk})
     launchOut.close('mapAttribute')
@@ -2307,9 +2318,7 @@
     if refresh:
         launchOut.element('stringAttribute',  {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE',            'value': '${project}'})
     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'})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND',       'value': 'true' if async else 'false'})
     
     baseDir = dirname(dirname(os.path.abspath(__file__)))
     
@@ -2329,7 +2338,7 @@
     
     if not exists(externalToolDir):
         os.makedirs(externalToolDir)
-    update_file(join(externalToolDir, name), launchOut.xml(indent='\t', newl='\n'))
+    update_file(join(externalToolDir, name), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n'))
     
     dotProjectDoc.open('buildCommand')
     dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
@@ -3009,9 +3018,10 @@
         if exists(tmpbase):
             shutil.rmtree(tmpbase)
 
-def findclass(args):
+def findclass(args, logToConsole=True):
     """find all classes matching a given substring"""
 
+    matches = []
     for entry, filename in classpath_walk(includeBootClasspath=True):
         if filename.endswith('.class'):
             if isinstance(entry, zipfile.ZipFile):
@@ -3021,20 +3031,19 @@
             classname = classname[:-len('.class')]
             for a in args:
                 if a in classname:
-                    log(classname)
+                    matches.append(classname)
+                    if logToConsole:
+                        log(classname)
+    return matches
 
 def javap(args):
-    """launch javap with a -classpath option denoting all available classes
-
-    Run the JDK javap class file disassembler with the following prepended options:
-
-        -private -verbose -classpath <path to project classes>"""
+    """disassemble classes matching given pattern with javap"""
 
     javap = java().javap
     if not exists(javap):
         abort('The javap executable does not exists: ' + javap)
     else:
-        run([javap, '-private', '-verbose', '-classpath', classpath()] + args)
+        run([javap, '-private', '-verbose', '-classpath', classpath()] + findclass(args, logToConsole=False))
 
 def show_projects(args):
     """show all loaded projects"""
@@ -3072,7 +3081,7 @@
     'ideinit': [ideinit, ''],
     'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
-    'javap': [javap, ''],
+    'javap': [javap, '<class name patterns>'],
     'javadoc': [javadoc, '[options]'],
     'site': [site, '[options]'],
     'netbeansinit': [netbeansinit, ''],
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -51,6 +51,16 @@
 void RangeCheckStub::emit_code(LIR_Assembler* ce) {
   __ bind(_entry);
 
+  if (_info->deoptimize_on_exception()) {
+    address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+    __ call(a, relocInfo::runtime_call_type);
+    __ delayed()->nop();
+    ce->add_call_info_here(_info);
+    ce->verify_oop_map(_info);
+    debug_only(__ should_not_reach_here());
+    return;
+  }
+
   if (_index->is_register()) {
     __ mov(_index->as_register(), G4);
   } else {
@@ -64,11 +74,22 @@
   __ delayed()->nop();
   ce->add_call_info_here(_info);
   ce->verify_oop_map(_info);
-#ifdef ASSERT
-  __ should_not_reach_here();
-#endif
+  debug_only(__ should_not_reach_here());
+}
+
+PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
+  _info = new CodeEmitInfo(info);
 }
 
+void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
+  __ bind(_entry);
+  address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+  __ call(a, relocInfo::runtime_call_type);
+  __ delayed()->nop();
+  ce->add_call_info_here(_info);
+  ce->verify_oop_map(_info);
+  debug_only(__ should_not_reach_here());
+}
 
 void CounterOverflowStub::emit_code(LIR_Assembler* ce) {
   __ bind(_entry);
@@ -99,10 +120,17 @@
 
 
 void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
+  address a;
+  if (_info->deoptimize_on_exception()) {
+    // Deoptimize, do not throw the exception, because it is probably wrong to do it here.
+    a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+  } else {
+    a = Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id);
+  }
+
   ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
   __ bind(_entry);
-  __ call(Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id),
-          relocInfo::runtime_call_type);
+  __ call(a, relocInfo::runtime_call_type);
   __ delayed()->nop();
   ce->add_call_info_here(_info);
   ce->verify_oop_map(_info);
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -3361,6 +3361,45 @@
   __ mov(G2_thread, result_reg->as_register());
 }
 
+#ifdef ASSERT
+// emit run-time assertion
+void LIR_Assembler::emit_assert(LIR_OpAssert* op) {
+  assert(op->code() == lir_assert, "must be");
+
+  if (op->in_opr1()->is_valid()) {
+    assert(op->in_opr2()->is_valid(), "both operands must be valid");
+    comp_op(op->condition(), op->in_opr1(), op->in_opr2(), op);
+  } else {
+    assert(op->in_opr2()->is_illegal(), "both operands must be illegal");
+    assert(op->condition() == lir_cond_always, "no other conditions allowed");
+  }
+
+  Label ok;
+  if (op->condition() != lir_cond_always) {
+    Assembler::Condition acond;
+    switch (op->condition()) {
+      case lir_cond_equal:        acond = Assembler::equal;                break;
+      case lir_cond_notEqual:     acond = Assembler::notEqual;             break;
+      case lir_cond_less:         acond = Assembler::less;                 break;
+      case lir_cond_lessEqual:    acond = Assembler::lessEqual;            break;
+      case lir_cond_greaterEqual: acond = Assembler::greaterEqual;         break;
+      case lir_cond_greater:      acond = Assembler::greater;              break;
+      case lir_cond_aboveEqual:   acond = Assembler::greaterEqualUnsigned; break;
+      case lir_cond_belowEqual:   acond = Assembler::lessEqualUnsigned;    break;
+      default:                         ShouldNotReachHere();
+    };
+    __ br(acond, false, Assembler::pt, ok);
+    __ delayed()->nop();
+  }
+  if (op->halt()) {
+    const char* str = __ code_string(op->msg());
+    __ stop(str);
+  } else {
+    breakpoint();
+  }
+  __ bind(ok);
+}
+#endif
 
 void LIR_Assembler::peephole(LIR_List* lir) {
   LIR_OpList* inst = lir->instructions_list();
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -324,7 +324,7 @@
 
 void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
   assert(x->is_pinned(),"");
-  bool needs_range_check = true;
+  bool needs_range_check = x->compute_needs_range_check();
   bool use_length = x->length() != NULL;
   bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
   bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
@@ -339,12 +339,9 @@
   array.load_item();
   index.load_nonconstant();
 
-  if (use_length) {
-    needs_range_check = x->compute_needs_range_check();
-    if (needs_range_check) {
-      length.set_instruction(x->length());
-      length.load_item();
-    }
+  if (use_length && needs_range_check) {
+    length.set_instruction(x->length());
+    length.load_item();
   }
   if (needs_store_check) {
     value.load_item();
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -987,6 +987,25 @@
       break;
 #endif // INCLUDE_ALL_GCS
 
+    case predicate_failed_trap_id:
+      {
+        __ set_info("predicate_failed_trap", dont_gc_arguments);
+        OopMap* oop_map = save_live_registers(sasm);
+
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap));
+
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, oop_map);
+
+        DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
+        assert(deopt_blob != NULL, "deoptimization blob must have been created");
+        restore_live_registers(sasm);
+        __ restore();
+        __ br(Assembler::always, false, Assembler::pt, deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type);
+        __ delayed()->nop();
+      }
+      break;
+
     default:
       { __ set_info("unimplemented entry", dont_gc_arguments);
         __ save_frame(0);
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -2194,7 +2194,8 @@
                                            int callee_locals_size,
                                            frame* caller,
                                            frame* interpreter_frame,
-                                           bool is_top_frame) {
+                                           bool is_top_frame,
+                                           bool is_bottom_frame) {
 
   assert(popframe_extra_args == 0, "NEED TO FIX");
   // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state()
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -381,6 +381,9 @@
     case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
     case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false);  break;
     case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);   break;
+#ifdef GRAAL
+    case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry();   break;
+#endif
     case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();        break;
     case Interpreter::accessor               : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry();     break;
     case Interpreter::abstract               : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry();     break;
--- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1385,13 +1385,13 @@
   }
 #endif
 
-  int len = strlen(file) + strlen(msg) + 1 + 4;
-  sprintf(buffer, "%d", line);
-  len += strlen(buffer);
-  sprintf(buffer, " at offset %d ", offset());
-  len += strlen(buffer);
-  char * real_msg = new char[len];
-  sprintf(real_msg, "%s%s(%s:%d)", msg, buffer, file, line);
+  const char* real_msg = NULL;
+  {
+    ResourceMark rm;
+    stringStream ss;
+    ss.print("%s at offset %d (%s:%d)", msg, offset(), file, line);
+    real_msg = code_string(ss.as_string());
+  }
 
   // Call indirectly to solve generation ordering problem
   AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address());
@@ -1423,13 +1423,13 @@
   // plausibility check for oops
   if (!VerifyOops) return;
 
-  char buffer[64];
-  sprintf(buffer, "%d", line);
-  int len = strlen(file) + strlen(msg) + 1 + 4 + strlen(buffer);
-  sprintf(buffer, " at SP+%d ", addr.disp());
-  len += strlen(buffer);
-  char * real_msg = new char[len];
-  sprintf(real_msg, "%s at SP+%d (%s:%d)", msg, addr.disp(), file, line);
+  const char* real_msg = NULL;
+  {
+    ResourceMark rm;
+    stringStream ss;
+    ss.print("%s at SP+%d (%s:%d)", msg, addr.disp(), file, line);
+    real_msg = code_string(ss.as_string());
+  }
 
   // Call indirectly to solve generation ordering problem
   AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address());
@@ -1622,9 +1622,13 @@
   // in order to run automated test scripts on the VM
   // Use the flag ShowMessageBoxOnError
 
-  char* b = new char[1024];
-  sprintf(b, "untested: %s", what);
-
+  const char* b = NULL;
+  {
+    ResourceMark rm;
+    stringStream ss;
+    ss.print("untested: %s", what);
+    b = code_string(ss.as_string());
+  }
   if (ShowMessageBoxOnError) { STOP(b); }
   else                       { warn(b); }
 }
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1581,7 +1581,8 @@
                                            int callee_local_count,
                                            frame* caller,
                                            frame* interpreter_frame,
-                                           bool is_top_frame) {
+                                           bool is_top_frame,
+                                           bool is_bottom_frame) {
   // Note: This calculation must exactly parallel the frame setup
   // in InterpreterGenerator::generate_fixed_frame.
   // If f!=NULL, set up the following variables:
@@ -1664,6 +1665,15 @@
       int delta = local_words - parm_words;
       int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0;
       *interpreter_frame->register_addr(I5_savedSP)    = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS;
+      if (!is_bottom_frame) {
+        // Llast_SP is set below for the current frame to SP (with the
+        // extra space for the callee's locals). Here we adjust
+        // Llast_SP for the caller's frame, removing the extra space
+        // for the current method's locals.
+        *caller->register_addr(Llast_SP) = *interpreter_frame->register_addr(I5_savedSP);
+      } else {
+        assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP");
+      }
     } else {
       assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases");
       // Don't have Lesp available; lay out locals block in the caller
--- a/src/cpu/x86/vm/assembler_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -214,14 +214,6 @@
   return enc;
 }
 
-static int encode(XMMRegister r) {
-  int enc = r->encoding();
-  if (enc >= 8) {
-    enc -= 8;
-  }
-  return enc;
-}
-
 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
   assert(dst->has_byte_register(), "must have byte register");
   assert(isByte(op1) && isByte(op2), "wrong opcode");
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -101,6 +101,15 @@
 
 void RangeCheckStub::emit_code(LIR_Assembler* ce) {
   __ bind(_entry);
+  if (_info->deoptimize_on_exception()) {
+    address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+    __ call(RuntimeAddress(a));
+    ce->add_call_info_here(_info);
+    ce->verify_oop_map(_info);
+    debug_only(__ should_not_reach_here());
+    return;
+  }
+
   // pass the array index on stack because all registers must be preserved
   if (_index->is_cpu_register()) {
     ce->store_parameter(_index->as_register(), 0);
@@ -115,9 +124,22 @@
   }
   __ call(RuntimeAddress(Runtime1::entry_for(stub_id)));
   ce->add_call_info_here(_info);
+  ce->verify_oop_map(_info);
   debug_only(__ should_not_reach_here());
 }
 
+PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
+  _info = new CodeEmitInfo(info);
+}
+
+void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
+  __ bind(_entry);
+  address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+  __ call(RuntimeAddress(a));
+  ce->add_call_info_here(_info);
+  ce->verify_oop_map(_info);
+  debug_only(__ should_not_reach_here());
+}
 
 void DivByZeroStub::emit_code(LIR_Assembler* ce) {
   if (_offset != -1) {
@@ -414,10 +436,19 @@
 
 
 void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
+  address a;
+  if (_info->deoptimize_on_exception()) {
+    // Deoptimize, do not throw the exception, because it is probably wrong to do it here.
+    a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);
+  } else {
+    a = Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id);
+  }
+
   ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
   __ bind(_entry);
-  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id)));
+  __ call(RuntimeAddress(a));
   ce->add_call_info_here(_info);
+  ce->verify_oop_map(_info);
   debug_only(__ should_not_reach_here());
 }
 
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -3755,6 +3755,44 @@
   }
 }
 
+#ifdef ASSERT
+// emit run-time assertion
+void LIR_Assembler::emit_assert(LIR_OpAssert* op) {
+  assert(op->code() == lir_assert, "must be");
+
+  if (op->in_opr1()->is_valid()) {
+    assert(op->in_opr2()->is_valid(), "both operands must be valid");
+    comp_op(op->condition(), op->in_opr1(), op->in_opr2(), op);
+  } else {
+    assert(op->in_opr2()->is_illegal(), "both operands must be illegal");
+    assert(op->condition() == lir_cond_always, "no other conditions allowed");
+  }
+
+  Label ok;
+  if (op->condition() != lir_cond_always) {
+    Assembler::Condition acond = Assembler::zero;
+    switch (op->condition()) {
+      case lir_cond_equal:        acond = Assembler::equal;       break;
+      case lir_cond_notEqual:     acond = Assembler::notEqual;    break;
+      case lir_cond_less:         acond = Assembler::less;        break;
+      case lir_cond_lessEqual:    acond = Assembler::lessEqual;   break;
+      case lir_cond_greaterEqual: acond = Assembler::greaterEqual;break;
+      case lir_cond_greater:      acond = Assembler::greater;     break;
+      case lir_cond_belowEqual:   acond = Assembler::belowEqual;  break;
+      case lir_cond_aboveEqual:   acond = Assembler::aboveEqual;  break;
+      default:                    ShouldNotReachHere();
+    }
+    __ jcc(acond, ok);
+  }
+  if (op->halt()) {
+    const char* str = __ code_string(op->msg());
+    __ stop(str);
+  } else {
+    breakpoint();
+  }
+  __ bind(ok);
+}
+#endif
 
 void LIR_Assembler::membar() {
   // QQQ sparc TSO uses this,
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -263,7 +263,7 @@
 
 void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
   assert(x->is_pinned(),"");
-  bool needs_range_check = true;
+  bool needs_range_check = x->compute_needs_range_check();
   bool use_length = x->length() != NULL;
   bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
   bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
@@ -278,12 +278,10 @@
   array.load_item();
   index.load_nonconstant();
 
-  if (use_length) {
-    needs_range_check = x->compute_needs_range_check();
-    if (needs_range_check) {
-      length.set_instruction(x->length());
-      length.load_item();
-    }
+  if (use_length && needs_range_check) {
+    length.set_instruction(x->length());
+    length.load_item();
+
   }
   if (needs_store_check) {
     value.load_item();
--- a/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -675,7 +675,8 @@
   switch (op2->code()) {
     case lir_cmp:
     case lir_cmp_fd2i:
-    case lir_ucmp_fd2i: {
+    case lir_ucmp_fd2i:
+    case lir_assert: {
       assert(left->is_fpu_register(), "invalid LIR");
       assert(right->is_fpu_register(), "invalid LIR");
 
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1807,6 +1807,24 @@
       break;
 #endif // INCLUDE_ALL_GCS
 
+    case predicate_failed_trap_id:
+      {
+        StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);
+
+        OopMap* map = save_live_registers(sasm, 1);
+
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap));
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, map);
+        restore_live_registers(sasm);
+        __ leave();
+        DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
+        assert(deopt_blob != NULL, "deoptimization blob must have been created");
+
+        __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));
+      }
+      break;
+
     default:
       { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments);
         __ movptr(rax, (int)id);
--- a/src/cpu/x86/vm/cppInterpreter_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1299,25 +1299,8 @@
   __ push(rdx);
 #endif // _LP64
 
-  // Either restore the MXCSR register after returning from the JNI Call
-  // or verify that it wasn't changed.
-  if (VM_Version::supports_sse()) {
-    if (RestoreMXCSROnJNICalls) {
-      __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std()));
-    }
-    else if (CheckJNICalls ) {
-      __ call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry()));
-    }
-  }
-
-#ifndef _LP64
-  // Either restore the x87 floating pointer control word after returning
-  // from the JNI call or verify that it wasn't changed.
-  if (CheckJNICalls) {
-    __ call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry()));
-  }
-#endif // _LP64
-
+  // Verify or restore cpu control state after JNI call
+  __ restore_cpu_control_state_after_jni();
 
   // change thread state
   __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
@@ -2361,7 +2344,8 @@
                                            int callee_locals,
                                            frame* caller,
                                            frame* interpreter_frame,
-                                           bool is_top_frame) {
+                                           bool is_top_frame,
+                                           bool is_bottom_frame) {
 
   assert(popframe_extra_args == 0, "FIX ME");
   // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state()
--- a/src/cpu/x86/vm/frame_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/frame_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -356,7 +356,7 @@
 // Verifies the calculated original PC of a deoptimization PC for the
 // given unextended SP.  The unextended SP might also be the saved SP
 // for MethodHandle call sites.
-#if ASSERT
+#ifdef ASSERT
 void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) {
   frame fr;
 
--- a/src/cpu/x86/vm/frame_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/frame_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -170,7 +170,7 @@
     return (intptr_t*) addr_at(offset);
   }
 
-#if ASSERT
+#ifdef ASSERT
   // Used in frame::sender_for_{interpreter,compiled}_frame
   static void verify_deopt_original_pc(   nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false);
   static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) {
--- a/src/cpu/x86/vm/frame_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/frame_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -295,14 +295,18 @@
   return true;
 }
 
-
+inline oop frame::saved_oop_result(RegisterMap* map) const {
+  oop* result_adr = (oop *)map->location(rax->as_VMReg());
+  guarantee(result_adr != NULL, "bad register save location");
 
-inline oop frame::saved_oop_result(RegisterMap* map) const       {
-  return *((oop*) map->location(rax->as_VMReg()));
+  return (*result_adr);
 }
 
 inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
-  *((oop*) map->location(rax->as_VMReg())) = obj;
+  oop* result_adr = (oop *)map->location(rax->as_VMReg());
+  guarantee(result_adr != NULL, "bad register save location");
+
+  *result_adr = obj;
 }
 
 #endif // CPU_X86_VM_FRAME_X86_INLINE_HPP
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -879,30 +879,10 @@
 
         // This is called via call_runtime so the arguments
         // will be place in C abi locations
-
-#ifdef _LP64
         __ verify_oop(j_rarg0);
-        __ mov(rax, j_rarg0);
-#else
-        // The object is passed on the stack and we haven't pushed a
-        // frame yet so it's one work away from top of stack.
-        __ movptr(rax, Address(rsp, 1 * BytesPerWord));
-        __ verify_oop(rax);
-#endif // _LP64
-
-        // load the klass and check the has finalizer flag
-        Label register_finalizer;
-        Register t = rsi;
-        __ load_klass(t, rax);
-        __ movl(t, Address(t, Klass::access_flags_offset()));
-        __ testl(t, JVM_ACC_HAS_FINALIZER);
-        __ jcc(Assembler::notZero, register_finalizer);
-        __ ret(0);
-
-        __ bind(register_finalizer);
         __ enter();
         OopMap* oop_map = save_live_registers(sasm, 2 /*num_rt_args */);
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), rax);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), j_rarg0);
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, oop_map);
 
@@ -950,6 +930,7 @@
 		OopMap* oop_map = save_live_registers(sasm, 0);
 		int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0);
 		oop_maps->add_gc_map(call_offset, oop_map);
+		restore_live_registers_except_rax(sasm);
 		__ leave();
 		__ ret(0);
       break;
@@ -958,9 +939,10 @@
     case create_out_of_bounds_exception_id: {
 		__ enter();
 		oop_maps = new OopMapSet();
-		OopMap* oop_map = save_live_registers(sasm, 0);
+		OopMap* oop_map = save_live_registers(sasm, 1);
 		int call_offset = __ call_RT(rax, noreg, (address)create_out_of_bounds_exception, j_rarg0);
 		oop_maps->add_gc_map(call_offset, oop_map);
+		restore_live_registers_except_rax(sasm);
 		__ leave();
 		__ ret(0);
       break;
@@ -969,7 +951,7 @@
     case vm_error_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 3);
       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);
@@ -981,7 +963,7 @@
     case log_printf_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 4);
       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);
@@ -993,7 +975,7 @@
     case log_primitive_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 3);
       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);
@@ -1005,7 +987,7 @@
     case log_object_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 2);
       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);
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -36,6 +36,9 @@
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
+#ifdef GRAAL
+  address generate_execute_compiled_method_entry();
+#endif
   address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/macroAssembler_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -4262,8 +4262,13 @@
   if (!VerifyOops) return;
 
   // Pass register number to verify_oop_subroutine
-  char* b = new char[strlen(s) + 50];
-  sprintf(b, "verify_oop: %s: %s", reg->name(), s);
+  const char* b = NULL;
+  {
+    ResourceMark rm;
+    stringStream ss;
+    ss.print("verify_oop: %s: %s", reg->name(), s);
+    b = code_string(ss.as_string());
+  }
   BLOCK_COMMENT("verify_oop {");
 #ifdef _LP64
   push(rscratch1);                    // save r10, trashed by movptr()
@@ -4297,9 +4302,14 @@
   { Label L;
     testptr(tmp, tmp);
     if (WizardMode) {
+      const char* buf = NULL;
+      {
+        ResourceMark rm;
+        stringStream ss;
+        ss.print("DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]);
+        buf = code_string(ss.as_string());
+      }
       jcc(Assembler::notZero, L);
-      char* buf = new char[40];
-      sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]);
       STOP(buf);
     } else {
       jccb(Assembler::notZero, L);
@@ -4343,9 +4353,13 @@
 
   // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord);
   // Pass register number to verify_oop_subroutine
-  char* b = new char[strlen(s) + 50];
-  sprintf(b, "verify_oop_addr: %s", s);
-
+  const char* b = NULL;
+  {
+    ResourceMark rm;
+    stringStream ss;
+    ss.print("verify_oop_addr: %s", s);
+    b = code_string(ss.as_string());
+  }
 #ifdef _LP64
   push(rscratch1);                    // save r10, trashed by movptr()
 #endif
@@ -4751,6 +4765,31 @@
   pop_CPU_state();
 }
 
+void MacroAssembler::restore_cpu_control_state_after_jni() {
+  // Either restore the MXCSR register after returning from the JNI Call
+  // or verify that it wasn't changed (with -Xcheck:jni flag).
+  if (VM_Version::supports_sse()) {
+    if (RestoreMXCSROnJNICalls) {
+      ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std()));
+    } else if (CheckJNICalls) {
+      call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry()));
+    }
+  }
+  if (VM_Version::supports_avx()) {
+    // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty.
+    vzeroupper();
+  }
+
+#ifndef _LP64
+  // Either restore the x87 floating pointer control word after returning
+  // from the JNI call or verify that it wasn't changed.
+  if (CheckJNICalls) {
+    call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry()));
+  }
+#endif // _LP64
+}
+
+
 void MacroAssembler::load_klass(Register dst, Register src) {
 #ifdef _LP64
   if (UseCompressedKlassPointers) {
@@ -5745,6 +5784,8 @@
     addptr(result, stride2);
     subl(cnt2, stride2);
     jccb(Assembler::notZero, COMPARE_WIDE_VECTORS_LOOP);
+    // clean upper bits of YMM registers
+    vzeroupper();
 
     // compare wide vectors tail
     bind(COMPARE_WIDE_TAIL);
@@ -5758,6 +5799,8 @@
 
     // Identifies the mismatching (higher or lower)16-bytes in the 32-byte vectors.
     bind(VECTOR_NOT_EQUAL);
+    // clean upper bits of YMM registers
+    vzeroupper();
     lea(str1, Address(str1, result, scale));
     lea(str2, Address(str2, result, scale));
     jmp(COMPARE_16_CHARS);
@@ -6014,6 +6057,10 @@
 
   // That's it
   bind(DONE);
+  if (UseAVX >= 2) {
+    // clean upper bits of YMM registers
+    vzeroupper();
+  }
 }
 
 void MacroAssembler::generate_fill(BasicType t, bool aligned,
@@ -6143,6 +6190,10 @@
         vmovdqu(Address(to, 0), xtmp);
         addptr(to, 32);
         subl(count, 8 << shift);
+
+        BIND(L_check_fill_8_bytes);
+        // clean upper bits of YMM registers
+        vzeroupper();
       } else {
         // Fill 32-byte chunks
         pshufd(xtmp, xtmp, 0);
@@ -6166,8 +6217,9 @@
         addptr(to, 32);
         subl(count, 8 << shift);
         jcc(Assembler::greaterEqual, L_fill_32_bytes_loop);
+
+        BIND(L_check_fill_8_bytes);
       }
-      BIND(L_check_fill_8_bytes);
       addl(count, 8 << shift);
       jccb(Assembler::zero, L_exit);
       jmpb(L_fill_8_bytes);
@@ -6302,6 +6354,10 @@
     jccb(Assembler::lessEqual, L_copy_16_chars);
 
     bind(L_copy_16_chars_exit);
+    if (UseAVX >= 2) {
+      // clean upper bits of YMM registers
+      vzeroupper();
+    }
     subptr(len, 8);
     jccb(Assembler::greater, L_copy_8_chars_exit);
 
--- a/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/macroAssembler_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -582,6 +582,9 @@
   // only if +VerifyFPU
   void verify_FPU(int stack_depth, const char* s = "illegal FPU state");
 
+  // Verify or restore cpu control state after JNI call
+  void restore_cpu_control_state_after_jni();
+
   // prints msg, dumps registers and stops execution
   void stop(const char* msg);
 
--- a/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -41,11 +41,6 @@
 
 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
 
-// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant.
-static RegisterOrConstant constant(int value) {
-  return RegisterOrConstant(value);
-}
-
 void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) {
   if (VerifyMethodHandles)
     verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class),
--- a/src/cpu/x86/vm/relocInfo_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/relocInfo_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -145,12 +145,9 @@
   assert(which == Assembler::disp32_operand ||
          which == Assembler::call32_operand ||
          which == Assembler::imm_operand, "format unpacks ok");
-  if (which != Assembler::imm_operand) {
-    // The "address" in the code is a displacement can't return it as
-    // and address* since it is really a jint*
-    ShouldNotReachHere();
-    return NULL;
-  }
+  // The "address" in the code is a displacement can't return it as
+  // and address* since it is really a jint*
+  guarantee(which == Assembler::imm_operand, "must be immediate operand");
 #else
   assert(which == Assembler::disp32_operand || which == Assembler::imm_operand, "format unpacks ok");
 #endif // AMD64
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -2065,6 +2065,9 @@
 
   __ call(RuntimeAddress(native_func));
 
+  // Verify or restore cpu control state after JNI call
+  __ restore_cpu_control_state_after_jni();
+
   // WARNING - on Windows Java Natives use pascal calling convention and pop the
   // arguments off of the stack. We could just re-adjust the stack pointer here
   // and continue to do SP relative addressing but we instead switch to FP
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1670,6 +1670,17 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+#ifdef GRAAL
+  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
+    // call to its verified entry point.
+    __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+    return;
+  }
+#endif
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
@@ -2326,16 +2337,8 @@
 
   __ call(RuntimeAddress(native_func));
 
-    // Either restore the MXCSR register after returning from the JNI Call
-    // or verify that it wasn't changed.
-    if (RestoreMXCSROnJNICalls) {
-      __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std()));
-
-    }
-    else if (CheckJNICalls ) {
-      __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::verify_mxcsr_entry())));
-    }
-
+  // Verify or restore cpu control state after JNI call
+  __ restore_cpu_control_state_after_jni();
 
   // Unpack native results.
   switch (ret_type) {
@@ -3338,6 +3341,10 @@
   __ jmp(cont);
 
   int reexecute_offset = __ pc() - start;
+#ifdef GRAALVM
+  // Graal does not use this kind of deoptimization
+  __ should_not_reach_here();
+#endif
 
   // Reexecute case
   // return address is the pc describes what bci to do re-execute at
@@ -3348,6 +3355,32 @@
   __ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved
   __ jmp(cont);
 
+#ifdef GRAAL
+  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())));
+
+  int uncommon_trap_offset = __ pc() - start;
+
+  // Save everything in sight.
+  RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+  // fetch_unroll_info needs to call last_java_frame()
+  __ set_last_Java_frame(noreg, noreg, NULL);
+
+  __ 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);
+  __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
+  oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
+
+  __ reset_last_Java_frame(false, false);
+
+  Label after_fetch_unroll_info_call;
+  __ jmp(after_fetch_unroll_info_call);
+#endif // GRAAL
+
   int exception_offset = __ pc() - start;
 
   // Prolog for exception case
@@ -3404,34 +3437,6 @@
   __ bind(no_pending_exception);
 #endif
 
-#ifdef GRAAL
-  __ 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())));
-
-  int uncommon_trap_offset = __ pc() - start;
-
-  // Save everything in sight.
-  RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
-  // fetch_unroll_info needs to call last_java_frame()
-  __ set_last_Java_frame(noreg, noreg, NULL);
-
-  __ 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);
-  __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
-  oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
-
-  __ reset_last_Java_frame(false, false);
-
-  Label after_fetch_unroll_info_call;
-  __ jmp(after_fetch_unroll_info_call);
-#endif // GRAAL
-
   __ bind(cont);
 
   // Call C code.  Need thread and this frame, but NOT official VM entry
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -835,6 +835,11 @@
   __ BIND(L_copy_64_bytes);
     __ subl(qword_count, 8);
     __ jcc(Assembler::greaterEqual, L_copy_64_bytes_loop);
+
+    if (UseUnalignedLoadStores && (UseAVX >= 2)) {
+      // clean upper bits of YMM registers
+      __ vzeroupper();
+    }
     __ addl(qword_count, 8);
     __ jccb(Assembler::zero, L_exit);
     //
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1331,6 +1331,10 @@
       }
       __ addptr(qword_count, 4);
       __ BIND(L_end);
+      if (UseAVX >= 2) {
+        // clean upper bits of YMM registers
+        __ vzeroupper();
+      }
     } else {
       // Copy 32-bytes per iteration
       __ BIND(L_loop);
@@ -1404,6 +1408,10 @@
       }
       __ subptr(qword_count, 4);
       __ BIND(L_end);
+      if (UseAVX >= 2) {
+        // clean upper bits of YMM registers
+        __ vzeroupper();
+      }
     } else {
       // Copy 32-bytes per iteration
       __ BIND(L_loop);
--- a/src/cpu/x86/vm/templateInterpreter_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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 = 224 * 1024;
+  const static int InterpreterCodeSize = 240 * 1024;
 #else
   const static int InterpreterCodeSize = 168 * 1024;
 #endif // AMD64
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1080,22 +1080,8 @@
 
   // result potentially in rdx:rax or ST0
 
-  // Either restore the MXCSR register after returning from the JNI Call
-  // or verify that it wasn't changed.
-  if (VM_Version::supports_sse()) {
-    if (RestoreMXCSROnJNICalls) {
-      __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std()));
-    }
-    else if (CheckJNICalls ) {
-      __ call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry()));
-    }
-  }
-
-  // Either restore the x87 floating pointer control word after returning
-  // from the JNI call or verify that it wasn't changed.
-  if (CheckJNICalls) {
-    __ call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry()));
-  }
+  // Verify or restore cpu control state after JNI call
+  __ restore_cpu_control_state_after_jni();
 
   // save potential result in ST(0) & rdx:rax
   // (if result handler is the T_FLOAT or T_DOUBLE handler, result must be in ST0 -
@@ -1585,7 +1571,8 @@
                                            int callee_locals,
                                            frame* caller,
                                            frame* interpreter_frame,
-                                           bool is_top_frame) {
+                                           bool is_top_frame,
+                                           bool is_bottom_frame) {
   // Note: This calculation must exactly parallel the frame setup
   // in AbstractInterpreterGenerator::generate_method_entry.
   // If interpreter_frame!=NULL, set up the method, locals, and monitors.
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -873,6 +873,46 @@
   return generate_accessor_entry();
 }
 
+#ifdef GRAAL
+
+// Interpreter stub for calling a compiled method with 3 object arguments
+address InterpreterGenerator::generate_execute_compiled_method_entry() {
+  address entry_point = __ pc();
+
+  // Pick up the return address
+  __ movptr(rax, Address(rsp, 0));
+
+  // Must preserve original SP for loading incoming arguments because
+  // we need to align the outgoing SP for compiled code.
+  __ movptr(r11, rsp);
+
+  // Ensure compiled code always sees stack at proper alignment
+  __ andptr(rsp, -16);
+
+  // push the return address and misalign the stack that youngest frame always sees
+  // as far as the placement of the call instruction
+  __ push(rax);
+
+  // Move first object argument from interpreter calling convention to compiled
+  // code calling convention.
+  __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+
+  // Move second object argument.
+  __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+
+  // Move third object argument.
+  __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+
+  // Load the raw pointer to the nmethod.
+  __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+
+  // Perform a tail call to the verified entry point of the nmethod.
+  __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
+  return entry_point;
+}
+
+#endif
 
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the
@@ -1123,15 +1163,8 @@
   __ call(rax);
   // result potentially in rax or xmm0
 
-  // Depending on runtime options, either restore the MXCSR
-  // register after returning from the JNI Call or verify that
-  // it wasn't changed during -Xcheck:jni.
-  if (RestoreMXCSROnJNICalls) {
-    __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std()));
-  }
-  else if (CheckJNICalls) {
-    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::verify_mxcsr_entry())));
-  }
+  // Verify or restore cpu control state after JNI call
+  __ restore_cpu_control_state_after_jni();
 
   // NOTE: The order of these pushes is known to frame::interpreter_frame_result
   // in order to extract the result of a method call. If the order of these
@@ -1568,6 +1601,9 @@
   switch (kind) {
   case Interpreter::zerolocals             :                                                                             break;
   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
+#ifdef GRAAL
+  case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break;
+#endif
   case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);  break;
   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();       break;
@@ -1643,7 +1679,8 @@
                                            int callee_locals,
                                            frame* caller,
                                            frame* interpreter_frame,
-                                           bool is_top_frame) {
+                                           bool is_top_frame,
+                                           bool is_bottom_frame) {
   // Note: This calculation must exactly parallel the frame setup
   // in AbstractInterpreterGenerator::generate_method_entry.
   // If interpreter_frame!=NULL, set up the method, locals, and monitors.
--- a/src/cpu/x86/vm/x86_32.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/x86_32.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -228,10 +228,16 @@
 static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
 
 // Offset hacking within calls.
-static int pre_call_FPU_size() {
-  if (Compile::current()->in_24_bit_fp_mode())
-    return 6; // fldcw
-  return 0;
+static int pre_call_resets_size() {
+  int size = 0;
+  Compile* C = Compile::current();
+  if (C->in_24_bit_fp_mode()) {
+    size += 6; // fldcw
+  }
+  if (C->max_vector_size() > 16) {
+    size += 3; // vzeroupper
+  }
+  return size;
 }
 
 static int preserve_SP_size() {
@@ -242,21 +248,21 @@
 //       from the start of the call to the point where the return address
 //       will point.
 int MachCallStaticJavaNode::ret_addr_offset() {
-  int offset = 5 + pre_call_FPU_size();  // 5 bytes from start of call to where return address points
+  int offset = 5 + pre_call_resets_size();  // 5 bytes from start of call to where return address points
   if (_method_handle_invoke)
     offset += preserve_SP_size();
   return offset;
 }
 
 int MachCallDynamicJavaNode::ret_addr_offset() {
-  return 10 + pre_call_FPU_size();  // 10 bytes from start of call to where return address points
+  return 10 + pre_call_resets_size();  // 10 bytes from start of call to where return address points
 }
 
 static int sizeof_FFree_Float_Stack_All = -1;
 
 int MachCallRuntimeNode::ret_addr_offset() {
   assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
-  return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size();
+  return sizeof_FFree_Float_Stack_All + 5 + pre_call_resets_size();
 }
 
 // Indicate if the safepoint node needs the polling page as an input.
@@ -272,7 +278,7 @@
 // The address of the call instruction needs to be 4-byte aligned to
 // ensure that it does not span a cache line so that it can be patched.
 int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
-  current_offset += pre_call_FPU_size();  // skip fldcw, if any
+  current_offset += pre_call_resets_size();  // skip fldcw, if any
   current_offset += 1;      // skip call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
 }
@@ -280,7 +286,7 @@
 // The address of the call instruction needs to be 4-byte aligned to
 // ensure that it does not span a cache line so that it can be patched.
 int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
-  current_offset += pre_call_FPU_size();  // skip fldcw, if any
+  current_offset += pre_call_resets_size();  // skip fldcw, if any
   current_offset += preserve_SP_size();   // skip mov rbp, rsp
   current_offset += 1;      // skip call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
@@ -289,7 +295,7 @@
 // The address of the call instruction needs to be 4-byte aligned to
 // ensure that it does not span a cache line so that it can be patched.
 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
-  current_offset += pre_call_FPU_size();  // skip fldcw, if any
+  current_offset += pre_call_resets_size();  // skip fldcw, if any
   current_offset += 5;      // skip MOV instruction
   current_offset += 1;      // skip call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
@@ -583,16 +589,20 @@
   // Remove two words for return addr and rbp,
   framesize -= 2*wordSize;
 
-  if( C->in_24_bit_fp_mode() ) {
+  if (C->max_vector_size() > 16) {
+    st->print("VZEROUPPER");
+    st->cr(); st->print("\t");
+  }
+  if (C->in_24_bit_fp_mode()) {
     st->print("FLDCW  standard control word");
     st->cr(); st->print("\t");
   }
-  if( framesize ) {
+  if (framesize) {
     st->print("ADD    ESP,%d\t# Destroy frame",framesize);
     st->cr(); st->print("\t");
   }
   st->print_cr("POPL   EBP"); st->print("\t");
-  if( do_polling() && C->is_method_compilation() ) {
+  if (do_polling() && C->is_method_compilation()) {
     st->print("TEST   PollPage,EAX\t! Poll Safepoint");
     st->cr(); st->print("\t");
   }
@@ -602,8 +612,14 @@
 void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
   Compile *C = ra_->C;
 
+  if (C->max_vector_size() > 16) {
+    // Clear upper bits of YMM registers when current compiled code uses
+    // wide vectors to avoid AVX <-> SSE transition penalty during call.
+    MacroAssembler masm(&cbuf);
+    masm.vzeroupper();
+  }
   // If method set FPU control word, restore to standard control word
-  if( C->in_24_bit_fp_mode() ) {
+  if (C->in_24_bit_fp_mode()) {
     MacroAssembler masm(&cbuf);
     masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
   }
@@ -615,12 +631,11 @@
 
   // Note that VerifyStackAtCalls' Majik cookie does not change the frame size popped here
 
-  if( framesize >= 128 ) {
+  if (framesize >= 128) {
     emit_opcode(cbuf, 0x81); // add  SP, #framesize
     emit_rm(cbuf, 0x3, 0x00, ESP_enc);
     emit_d32(cbuf, framesize);
-  }
-  else if( framesize ) {
+  } else if (framesize) {
     emit_opcode(cbuf, 0x83); // add  SP, #framesize
     emit_rm(cbuf, 0x3, 0x00, ESP_enc);
     emit_d8(cbuf, framesize);
@@ -628,7 +643,7 @@
 
   emit_opcode(cbuf, 0x58 | EBP_enc);
 
-  if( do_polling() && C->is_method_compilation() ) {
+  if (do_polling() && C->is_method_compilation()) {
     cbuf.relocate(cbuf.insts_end(), relocInfo::poll_return_type, 0);
     emit_opcode(cbuf,0x85);
     emit_rm(cbuf, 0x0, EAX_enc, 0x5); // EAX
@@ -640,7 +655,8 @@
   Compile *C = ra_->C;
   // If method set FPU control word, restore to standard control word
   int size = C->in_24_bit_fp_mode() ? 6 : 0;
-  if( do_polling() && C->is_method_compilation() ) size += 6;
+  if (C->max_vector_size() > 16) size += 3; // vzeroupper
+  if (do_polling() && C->is_method_compilation()) size += 6;
 
   int framesize = C->frame_slots() << LogBytesPerInt;
   assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
@@ -649,7 +665,7 @@
 
   size++; // popl rbp,
 
-  if( framesize >= 128 ) {
+  if (framesize >= 128) {
     size += 6;
   } else {
     size += framesize ? 3 : 0;
@@ -1853,20 +1869,26 @@
   %}
 
 
-  enc_class pre_call_FPU %{
+  enc_class pre_call_resets %{
     // If method sets FPU control word restore it here
     debug_only(int off0 = cbuf.insts_size());
-    if( Compile::current()->in_24_bit_fp_mode() ) {
-      MacroAssembler masm(&cbuf);
-      masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
+    if (ra_->C->in_24_bit_fp_mode()) {
+      MacroAssembler _masm(&cbuf);
+      __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
+    }
+    if (ra_->C->max_vector_size() > 16) {
+      // Clear upper bits of YMM registers when current compiled code uses
+      // wide vectors to avoid AVX <-> SSE transition penalty during call.
+      MacroAssembler _masm(&cbuf);
+      __ vzeroupper();
     }
     debug_only(int off1 = cbuf.insts_size());
-    assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction");
+    assert(off1 - off0 == pre_call_resets_size(), "correct size prediction");
   %}
 
   enc_class post_call_FPU %{
     // If method sets FPU control word do it here also
-    if( Compile::current()->in_24_bit_fp_mode() ) {
+    if (Compile::current()->in_24_bit_fp_mode()) {
       MacroAssembler masm(&cbuf);
       masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24()));
     }
@@ -1877,17 +1899,17 @@
     // who we intended to call.
     cbuf.set_insts_mark();
     $$$emit8$primary;
-    if ( !_method ) {
+    if (!_method) {
       emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4),
                      runtime_call_Relocation::spec(), RELOC_IMM32 );
-    } else if(_optimized_virtual) {
+    } else if (_optimized_virtual) {
       emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4),
                      opt_virtual_call_Relocation::spec(), RELOC_IMM32 );
     } else {
       emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4),
                      static_call_Relocation::spec(), RELOC_IMM32 );
     }
-    if( _method ) {  // Emit stub for static call
+    if (_method) {  // Emit stub for static call
       emit_java_to_interp(cbuf);
     }
   %}
@@ -12828,7 +12850,7 @@
   ins_cost(300);
   format %{ "CALL,static " %}
   opcode(0xE8); /* E8 cd */
-  ins_encode( pre_call_FPU,
+  ins_encode( pre_call_resets,
               Java_Static_Call( meth ),
               call_epilog,
               post_call_FPU );
@@ -12849,7 +12871,7 @@
   ins_cost(300);
   format %{ "CALL,static/MethodHandle " %}
   opcode(0xE8); /* E8 cd */
-  ins_encode( pre_call_FPU,
+  ins_encode( pre_call_resets,
               preserve_SP,
               Java_Static_Call( meth ),
               restore_SP,
@@ -12870,7 +12892,7 @@
   format %{ "MOV    EAX,(oop)-1\n\t"
             "CALL,dynamic" %}
   opcode(0xE8); /* E8 cd */
-  ins_encode( pre_call_FPU,
+  ins_encode( pre_call_resets,
               Java_Dynamic_Call( meth ),
               call_epilog,
               post_call_FPU );
@@ -12887,7 +12909,7 @@
   format %{ "CALL,runtime " %}
   opcode(0xE8); /* E8 cd */
   // Use FFREEs to clear entries in float stack
-  ins_encode( pre_call_FPU,
+  ins_encode( pre_call_resets,
               FFree_Float_Stack_All,
               Java_To_Runtime( meth ),
               post_call_FPU );
@@ -12902,7 +12924,7 @@
   ins_cost(300);
   format %{ "CALL_LEAF,runtime " %}
   opcode(0xE8); /* E8 cd */
-  ins_encode( pre_call_FPU,
+  ins_encode( pre_call_resets,
               FFree_Float_Stack_All,
               Java_To_Runtime( meth ),
               Verify_FPU_For_Leaf, post_call_FPU );
--- a/src/cpu/x86/vm/x86_64.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/x86/vm/x86_64.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -399,6 +399,9 @@
 static int preserve_SP_size() {
   return 3;  // rex.w, op, rm(reg/reg)
 }
+static int clear_avx_size() {
+  return (Compile::current()->max_vector_size() > 16) ? 3 : 0;  // vzeroupper
+}
 
 // !!!!! Special hack to get all types of calls to specify the byte offset
 //       from the start of the call to the point where the return address
@@ -406,6 +409,7 @@
 int MachCallStaticJavaNode::ret_addr_offset()
 {
   int offset = 5; // 5 bytes from start of call to where return address points
+  offset += clear_avx_size();
   if (_method_handle_invoke)
     offset += preserve_SP_size();
   return offset;
@@ -413,11 +417,16 @@
 
 int MachCallDynamicJavaNode::ret_addr_offset()
 {
-  return 15; // 15 bytes from start of call to where return address points
+  int offset = 15; // 15 bytes from start of call to where return address points
+  offset += clear_avx_size();
+  return offset;
 }
 
-// In os_cpu .ad file
-// int MachCallRuntimeNode::ret_addr_offset()
+int MachCallRuntimeNode::ret_addr_offset() {
+  int offset = 13; // movq r10,#addr; callq (r10)
+  offset += clear_avx_size();
+  return offset;
+}
 
 // Indicate if the safepoint node needs the polling page as an input,
 // it does if the polling page is more than disp32 away.
@@ -434,6 +443,7 @@
 // ensure that it does not span a cache line so that it can be patched.
 int CallStaticJavaDirectNode::compute_padding(int current_offset) const
 {
+  current_offset += clear_avx_size(); // skip vzeroupper
   current_offset += 1; // skip call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
 }
@@ -443,6 +453,7 @@
 int CallStaticJavaHandleNode::compute_padding(int current_offset) const
 {
   current_offset += preserve_SP_size();   // skip mov rbp, rsp
+  current_offset += clear_avx_size(); // skip vzeroupper
   current_offset += 1; // skip call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
 }
@@ -451,6 +462,7 @@
 // ensure that it does not span a cache line so that it can be patched.
 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
 {
+  current_offset += clear_avx_size(); // skip vzeroupper
   current_offset += 11; // skip movq instruction + call opcode byte
   return round_to(current_offset, alignment_required()) - current_offset;
 }
@@ -764,6 +776,11 @@
 void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
 {
   Compile* C = ra_->C;
+  if (C->max_vector_size() > 16) {
+    st->print("vzeroupper");
+    st->cr(); st->print("\t");
+  }
+
   int framesize = C->frame_slots() << LogBytesPerInt;
   assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
   // Remove word for return adr already pushed
@@ -793,6 +810,13 @@
 void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
 {
   Compile* C = ra_->C;
+  if (C->max_vector_size() > 16) {
+    // Clear upper bits of YMM registers when current compiled code uses
+    // wide vectors to avoid AVX <-> SSE transition penalty during call.
+    MacroAssembler _masm(&cbuf);
+    __ vzeroupper();
+  }
+
   int framesize = C->frame_slots() << LogBytesPerInt;
   assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
   // Remove word for return adr already pushed
@@ -1669,17 +1693,6 @@
   return PTR_RBP_REG_mask();
 }
 
-static Address build_address(int b, int i, int s, int d) {
-  Register index = as_Register(i);
-  Address::ScaleFactor scale = (Address::ScaleFactor)s;
-  if (index == rsp) {
-    index = noreg;
-    scale = Address::no_scale;
-  }
-  Address addr(as_Register(b), index, scale, d);
-  return addr;
-}
-
 %}
 
 //----------ENCODING BLOCK-----------------------------------------------------
@@ -2008,6 +2021,25 @@
     __ bind(miss);
   %}
 
+  enc_class clear_avx %{
+    debug_only(int off0 = cbuf.insts_size());
+    if (ra_->C->max_vector_size() > 16) {
+      // Clear upper bits of YMM registers when current compiled code uses
+      // wide vectors to avoid AVX <-> SSE transition penalty during call.
+      MacroAssembler _masm(&cbuf);
+      __ vzeroupper();
+    }
+    debug_only(int off1 = cbuf.insts_size());
+    assert(off1 - off0 == clear_avx_size(), "correct size prediction");
+  %}
+
+  enc_class Java_To_Runtime(method meth) %{
+    // No relocation needed
+    MacroAssembler _masm(&cbuf);
+    __ mov64(r10, (int64_t) $meth$$method);
+    __ call(r10);
+  %}
+
   enc_class Java_To_Interpreter(method meth)
   %{
     // CALL Java_To_Interpreter
@@ -11366,7 +11398,7 @@
   ins_cost(300);
   format %{ "call,static " %}
   opcode(0xE8); /* E8 cd */
-  ins_encode(Java_Static_Call(meth), call_epilog);
+  ins_encode(clear_avx, Java_Static_Call(meth), call_epilog);
   ins_pipe(pipe_slow);
   ins_alignment(4);
 %}
@@ -11384,7 +11416,7 @@
   ins_cost(300);
   format %{ "call,static/MethodHandle " %}
   opcode(0xE8); /* E8 cd */
-  ins_encode(preserve_SP,
+  ins_encode(clear_avx, preserve_SP,
              Java_Static_Call(meth),
              restore_SP,
              call_epilog);
@@ -11403,7 +11435,7 @@
   ins_cost(300);
   format %{ "movq    rax, #Universe::non_oop_word()\n\t"
             "call,dynamic " %}
-  ins_encode(Java_Dynamic_Call(meth), call_epilog);
+  ins_encode(clear_avx, Java_Dynamic_Call(meth), call_epilog);
   ins_pipe(pipe_slow);
   ins_alignment(4);
 %}
@@ -11416,8 +11448,7 @@
 
   ins_cost(300);
   format %{ "call,runtime " %}
-  opcode(0xE8); /* E8 cd */
-  ins_encode(Java_To_Runtime(meth));
+  ins_encode(clear_avx, Java_To_Runtime(meth));
   ins_pipe(pipe_slow);
 %}
 
@@ -11429,8 +11460,7 @@
 
   ins_cost(300);
   format %{ "call_leaf,runtime " %}
-  opcode(0xE8); /* E8 cd */
-  ins_encode(Java_To_Runtime(meth));
+  ins_encode(clear_avx, Java_To_Runtime(meth));
   ins_pipe(pipe_slow);
 %}
 
@@ -11442,7 +11472,6 @@
 
   ins_cost(300);
   format %{ "call_leaf_nofp,runtime " %}
-  opcode(0xE8); /* E8 cd */
   ins_encode(Java_To_Runtime(meth));
   ins_pipe(pipe_slow);
 %}
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -919,7 +919,8 @@
                                            int       callee_locals,
                                            frame*    caller,
                                            frame*    interpreter_frame,
-                                           bool      is_top_frame) {
+                                           bool      is_top_frame,
+                                           bool      is_bottom_frame) {
   assert(popframe_extra_args == 0, "what to do?");
   assert(!is_top_frame || (!callee_locals && !callee_param_count),
          "top frame should have no caller");
--- a/src/os/bsd/vm/os_bsd.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/bsd/vm/os_bsd.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -57,6 +57,7 @@
 #include "runtime/threadCritical.hpp"
 #include "runtime/timer.hpp"
 #include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
@@ -151,7 +152,6 @@
 // utility functions
 
 static int SR_initialize();
-static int SR_finalize();
 
 julong os::available_memory() {
   return Bsd::available_memory();
@@ -166,20 +166,6 @@
   return Bsd::physical_memory();
 }
 
-julong os::allocatable_physical_memory(julong size) {
-#ifdef _LP64
-  return size;
-#else
-  julong result = MIN2(size, (julong)3800*M);
-   if (!is_allocatable(result)) {
-     // See comments under solaris for alignment considerations
-     julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
-     result =  MIN2(size, reasonable_size);
-   }
-   return result;
-#endif // _LP64
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // environment support
 
@@ -1213,6 +1199,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // Really shouldn't be NULL, but check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -2275,13 +2264,25 @@
      return NULL;
   }
 
+  // The memory is committed
+  address pc = CALLER_PC;
+  MemTracker::record_virtual_memory_reserve((address)addr, bytes, pc);
+  MemTracker::record_virtual_memory_commit((address)addr, bytes, pc);
+
   return addr;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
   // detaching the SHM segment will also delete it, see reserve_memory_special()
   int rslt = shmdt(base);
-  return rslt == 0;
+  if (rslt == 0) {
+    MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+    MemTracker::record_virtual_memory_release((address)base, bytes);
+    return true;
+  } else {
+    return false;
+  }
+
 }
 
 size_t os::large_page_size() {
@@ -2695,7 +2696,7 @@
   assert(thread->is_VM_thread(), "Must be VMThread");
   // read current suspend action
   int action = osthread->sr.suspend_action();
-  if (action == SR_SUSPEND) {
+  if (action == os::Bsd::SuspendResume::SR_SUSPEND) {
     suspend_save_context(osthread, siginfo, context);
 
     // Notify the suspend action is about to be completed. do_suspend()
@@ -2717,12 +2718,12 @@
     do {
       sigsuspend(&suspend_set);
       // ignore all returns until we get a resume signal
-    } while (osthread->sr.suspend_action() != SR_CONTINUE);
+    } while (osthread->sr.suspend_action() != os::Bsd::SuspendResume::SR_CONTINUE);
 
     resume_clear_context(osthread);
 
   } else {
-    assert(action == SR_CONTINUE, "unexpected sr action");
+    assert(action == os::Bsd::SuspendResume::SR_CONTINUE, "unexpected sr action");
     // nothing special to do - just leave the handler
   }
 
@@ -2767,16 +2768,12 @@
   return 0;
 }
 
-static int SR_finalize() {
-  return 0;
-}
-
 
 // returns true on success and false on error - really an error is fatal
 // but this seems the normal response to library errors
 static bool do_suspend(OSThread* osthread) {
   // mark as suspended and send signal
-  osthread->sr.set_suspend_action(SR_SUSPEND);
+  osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_SUSPEND);
   int status = pthread_kill(osthread->pthread_id(), SR_signum);
   assert_status(status == 0, status, "pthread_kill");
 
@@ -2785,18 +2782,18 @@
     for (int i = 0; !osthread->sr.is_suspended(); i++) {
       os::yield_all(i);
     }
-    osthread->sr.set_suspend_action(SR_NONE);
+    osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE);
     return true;
   }
   else {
-    osthread->sr.set_suspend_action(SR_NONE);
+    osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE);
     return false;
   }
 }
 
 static void do_resume(OSThread* osthread) {
   assert(osthread->sr.is_suspended(), "thread should be suspended");
-  osthread->sr.set_suspend_action(SR_CONTINUE);
+  osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_CONTINUE);
 
   int status = pthread_kill(osthread->pthread_id(), SR_signum);
   assert_status(status == 0, status, "pthread_kill");
@@ -2806,7 +2803,7 @@
       os::yield_all(i);
     }
   }
-  osthread->sr.set_suspend_action(SR_NONE);
+  osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -3579,16 +3576,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
-static address same_page(address x, address y) {
-  int page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -3612,8 +3599,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
@@ -3903,15 +3890,27 @@
 jlong os::current_thread_cpu_time() {
 #ifdef __APPLE__
   return os::thread_cpu_time(Thread::current(), true /* user + sys */);
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
 jlong os::thread_cpu_time(Thread* thread) {
+#ifdef __APPLE__
+  return os::thread_cpu_time(thread, true /* user + sys */);
+#else
+  Unimplemented();
+  return 0;
+#endif
 }
 
 jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
 #ifdef __APPLE__
   return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
@@ -3935,6 +3934,9 @@
   } else {
     return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000);
   }
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
--- a/src/os/bsd/vm/os_bsd.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/bsd/vm/os_bsd.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -151,36 +151,25 @@
   // for BsdThreads are no longer needed.
   class SuspendResume {
   private:
-    volatile int _suspend_action;
+    volatile int  _suspend_action;
+    volatile jint _state;
+  public:
     // values for suspend_action:
-    #define SR_NONE               (0x00)
-    #define SR_SUSPEND            (0x01)  // suspend request
-    #define SR_CONTINUE           (0x02)  // resume request
+    enum {
+      SR_NONE              = 0x00,
+      SR_SUSPEND           = 0x01,  // suspend request
+      SR_CONTINUE          = 0x02,  // resume request
+      SR_SUSPENDED         = 0x20   // values for _state: + SR_NONE
+    };
 
-    volatile jint _state;
-    // values for _state: + SR_NONE
-    #define SR_SUSPENDED          (0x20)
-  public:
     SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; }
 
     int suspend_action() const     { return _suspend_action; }
     void set_suspend_action(int x) { _suspend_action = x;    }
 
     // atomic updates for _state
-    void set_suspended()           {
-      jint temp, temp2;
-      do {
-        temp = _state;
-        temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
-      } while (temp2 != temp);
-    }
-    void clear_suspended()        {
-      jint temp, temp2;
-      do {
-        temp = _state;
-        temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
-      } while (temp2 != temp);
-    }
+    inline void set_suspended();
+    inline void clear_suspended();
     bool is_suspended()            { return _state & SR_SUSPENDED;       }
 
     #undef SR_SUSPENDED
--- a/src/os/bsd/vm/os_bsd.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/bsd/vm/os_bsd.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,6 @@
 #ifndef OS_BSD_VM_OS_BSD_INLINE_HPP
 #define OS_BSD_VM_OS_BSD_INLINE_HPP
 
-#include "runtime/atomic.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 
@@ -286,4 +285,21 @@
                             const char* optval, socklen_t optlen) {
   return ::setsockopt(fd, level, optname, optval, optlen);
 }
+
+inline void os::Bsd::SuspendResume::set_suspended()           {
+  jint temp, temp2;
+  do {
+    temp = _state;
+    temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
+  } while (temp2 != temp);
+}
+
+inline void os::Bsd::SuspendResume::clear_suspended()        {
+  jint temp, temp2;
+  do {
+    temp = _state;
+    temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
+  } while (temp2 != temp);
+}
+
 #endif // OS_BSD_VM_OS_BSD_INLINE_HPP
--- a/src/os/bsd/vm/perfMemory_bsd.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -672,15 +672,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -828,7 +828,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -899,9 +899,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/linux/vm/globals_linux.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/linux/vm/globals_linux.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -40,6 +40,9 @@
   product(bool, UseHugeTLBFS, false,                                    \
           "Use MAP_HUGETLB for large pages")                            \
                                                                         \
+  product(bool, LoadExecStackDllInVMThread, true,                       \
+          "Load DLLs with executable-stack attribute in the VM Thread") \
+                                                                        \
   product(bool, UseSHM, false,                                          \
           "Use SYSV shared memory for large pages")
 
--- a/src/os/linux/vm/os_linux.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/linux/vm/os_linux.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -44,6 +44,7 @@
 #include "runtime/extendedPC.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/init.hpp"
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
@@ -57,10 +58,12 @@
 #include "runtime/threadCritical.hpp"
 #include "runtime/timer.hpp"
 #include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/events.hpp"
+#include "utilities/elfFile.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/vmError.hpp"
 
@@ -173,7 +176,6 @@
 // utility functions
 
 static int SR_initialize();
-static int SR_finalize();
 
 julong os::available_memory() {
   return Linux::available_memory();
@@ -191,20 +193,6 @@
   return Linux::physical_memory();
 }
 
-julong os::allocatable_physical_memory(julong size) {
-#ifdef _LP64
-  return size;
-#else
-  julong result = MIN2(size, (julong)3800*M);
-   if (!is_allocatable(result)) {
-     // See comments under solaris for alignment considerations
-     julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
-     result =  MIN2(size, reasonable_size);
-   }
-   return result;
-#endif // _LP64
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // environment support
 
@@ -1644,6 +1632,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // Really shouldn't be NULL, but check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -1796,20 +1787,101 @@
   // in case of error it checks if .dll/.so was built for the
   // same architecture as Hotspot is running on
 
+
+// Remember the stack's state. The Linux dynamic linker will change
+// the stack to 'executable' at most once, so we must safepoint only once.
+bool os::Linux::_stack_is_executable = false;
+
+// VM operation that loads a library.  This is necessary if stack protection
+// of the Java stacks can be lost during loading the library.  If we
+// do not stop the Java threads, they can stack overflow before the stacks
+// are protected again.
+class VM_LinuxDllLoad: public VM_Operation {
+ private:
+  const char *_filename;
+  char *_ebuf;
+  int _ebuflen;
+  void *_lib;
+ public:
+  VM_LinuxDllLoad(const char *fn, char *ebuf, int ebuflen) :
+    _filename(fn), _ebuf(ebuf), _ebuflen(ebuflen), _lib(NULL) {}
+  VMOp_Type type() const { return VMOp_LinuxDllLoad; }
+  void doit() {
+    _lib = os::Linux::dll_load_in_vmthread(_filename, _ebuf, _ebuflen);
+    os::Linux::_stack_is_executable = true;
+  }
+  void* loaded_library() { return _lib; }
+};
+
 void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
 {
-  void * result= ::dlopen(filename, RTLD_LAZY);
+  void * result = NULL;
+  bool load_attempted = false;
+
+  // Check whether the library to load might change execution rights
+  // of the stack. If they are changed, the protection of the stack
+  // guard pages will be lost. We need a safepoint to fix this.
+  //
+  // See Linux man page execstack(8) for more info.
+  if (os::uses_stack_guard_pages() && !os::Linux::_stack_is_executable) {
+    ElfFile ef(filename);
+    if (!ef.specifies_noexecstack()) {
+      if (!is_init_completed()) {
+        os::Linux::_stack_is_executable = true;
+        // This is OK - No Java threads have been created yet, and hence no
+        // stack guard pages to fix.
+        //
+        // This should happen only when you are building JDK7 using a very
+        // old version of JDK6 (e.g., with JPRT) and running test_gamma.
+        //
+        // Dynamic loader will make all stacks executable after
+        // this function returns, and will not do that again.
+        assert(Threads::first() == NULL, "no Java threads should exist yet.");
+      } else {
+        warning("You have loaded library %s which might have disabled stack guard. "
+                "The VM will try to fix the stack guard now.\n"
+                "It's highly recommended that you fix the library with "
+                "'execstack -c <libfile>', or link it with '-z noexecstack'.",
+                filename);
+
+        assert(Thread::current()->is_Java_thread(), "must be Java thread");
+        JavaThread *jt = JavaThread::current();
+        if (jt->thread_state() != _thread_in_native) {
+          // This happens when a compiler thread tries to load a hsdis-<arch>.so file
+          // that requires ExecStack. Cannot enter safe point. Let's give up.
+          warning("Unable to fix stack guard. Giving up.");
+        } else {
+          if (!LoadExecStackDllInVMThread) {
+            // This is for the case where the DLL has an static
+            // constructor function that executes JNI code. We cannot
+            // load such DLLs in the VMThread.
+            result = os::Linux::dlopen_helper(filename, ebuf, ebuflen);
+          }
+
+          ThreadInVMfromNative tiv(jt);
+          debug_only(VMNativeEntryWrapper vew;)
+
+          VM_LinuxDllLoad op(filename, ebuf, ebuflen);
+          VMThread::execute(&op);
+          if (LoadExecStackDllInVMThread) {
+            result = op.loaded_library();
+          }
+          load_attempted = true;
+        }
+      }
+    }
+  }
+
+  if (!load_attempted) {
+    result = os::Linux::dlopen_helper(filename, ebuf, ebuflen);
+  }
+
   if (result != NULL) {
     // Successful loading
     return result;
   }
 
   Elf32_Ehdr elf_head;
-
-  // Read system error message into ebuf
-  // It may or may not be overwritten below
-  ::strncpy(ebuf, ::dlerror(), ebuflen-1);
-  ebuf[ebuflen-1]='\0';
   int diag_msg_max_length=ebuflen-strlen(ebuf);
   char* diag_msg_buf=ebuf+strlen(ebuf);
 
@@ -1952,6 +2024,47 @@
   return NULL;
 }
 
+void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
+  void * result = ::dlopen(filename, RTLD_LAZY);
+  if (result == NULL) {
+    ::strncpy(ebuf, ::dlerror(), ebuflen - 1);
+    ebuf[ebuflen-1] = '\0';
+  }
+  return result;
+}
+
+void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf, int ebuflen) {
+  void * result = NULL;
+  if (LoadExecStackDllInVMThread) {
+    result = dlopen_helper(filename, ebuf, ebuflen);
+  }
+
+  // Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a
+  // library that requires an executable stack, or which does not have this
+  // stack attribute set, dlopen changes the stack attribute to executable. The
+  // read protection of the guard pages gets lost.
+  //
+  // Need to check _stack_is_executable again as multiple VM_LinuxDllLoad
+  // may have been queued at the same time.
+
+  if (!_stack_is_executable) {
+    JavaThread *jt = Threads::first();
+
+    while (jt) {
+      if (!jt->stack_guard_zone_unused() &&        // Stack not yet fully initialized
+          jt->stack_yellow_zone_enabled()) {       // No pending stack overflow exceptions
+        if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(),
+                              jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) {
+          warning("Attempt to reguard stack yellow zone failed.");
+        }
+      }
+      jt = jt->next();
+    }
+  }
+
+  return result;
+}
+
 /*
  * glibc-2.0 libdl is not MT safe.  If you are building with any glibc,
  * chances are you might want to run the generated bits against glibc-2.0
@@ -3094,13 +3207,24 @@
     numa_make_global(addr, bytes);
   }
 
+  // The memory is committed
+  address pc = CALLER_PC;
+  MemTracker::record_virtual_memory_reserve((address)addr, bytes, pc);
+  MemTracker::record_virtual_memory_commit((address)addr, bytes, pc);
+
   return addr;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
   // detaching the SHM segment will also delete it, see reserve_memory_special()
   int rslt = shmdt(base);
-  return rslt == 0;
+  if (rslt == 0) {
+    MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+    MemTracker::record_virtual_memory_release((address)base, bytes);
+    return true;
+  } else {
+   return false;
+  }
 }
 
 size_t os::large_page_size() {
@@ -3461,7 +3585,7 @@
   assert(thread->is_VM_thread(), "Must be VMThread");
   // read current suspend action
   int action = osthread->sr.suspend_action();
-  if (action == SR_SUSPEND) {
+  if (action == os::Linux::SuspendResume::SR_SUSPEND) {
     suspend_save_context(osthread, siginfo, context);
 
     // Notify the suspend action is about to be completed. do_suspend()
@@ -3483,12 +3607,12 @@
     do {
       sigsuspend(&suspend_set);
       // ignore all returns until we get a resume signal
-    } while (osthread->sr.suspend_action() != SR_CONTINUE);
+    } while (osthread->sr.suspend_action() != os::Linux::SuspendResume::SR_CONTINUE);
 
     resume_clear_context(osthread);
 
   } else {
-    assert(action == SR_CONTINUE, "unexpected sr action");
+    assert(action == os::Linux::SuspendResume::SR_CONTINUE, "unexpected sr action");
     // nothing special to do - just leave the handler
   }
 
@@ -3533,16 +3657,12 @@
   return 0;
 }
 
-static int SR_finalize() {
-  return 0;
-}
-
 
 // returns true on success and false on error - really an error is fatal
 // but this seems the normal response to library errors
 static bool do_suspend(OSThread* osthread) {
   // mark as suspended and send signal
-  osthread->sr.set_suspend_action(SR_SUSPEND);
+  osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_SUSPEND);
   int status = pthread_kill(osthread->pthread_id(), SR_signum);
   assert_status(status == 0, status, "pthread_kill");
 
@@ -3551,18 +3671,18 @@
     for (int i = 0; !osthread->sr.is_suspended(); i++) {
       os::yield_all(i);
     }
-    osthread->sr.set_suspend_action(SR_NONE);
+    osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE);
     return true;
   }
   else {
-    osthread->sr.set_suspend_action(SR_NONE);
+    osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE);
     return false;
   }
 }
 
 static void do_resume(OSThread* osthread) {
   assert(osthread->sr.is_suspended(), "thread should be suspended");
-  osthread->sr.set_suspend_action(SR_CONTINUE);
+  osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_CONTINUE);
 
   int status = pthread_kill(osthread->pthread_id(), SR_signum);
   assert_status(status == 0, status, "pthread_kill");
@@ -3572,7 +3692,7 @@
       os::yield_all(i);
     }
   }
-  osthread->sr.set_suspend_action(SR_NONE);
+  osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -4378,16 +4498,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
-static address same_page(address x, address y) {
-  int page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -4411,8 +4521,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
--- a/src/os/linux/vm/os_linux.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/linux/vm/os_linux.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -94,6 +94,10 @@
   static void print_libversion_info(outputStream* st);
 
  public:
+  static bool _stack_is_executable;
+  static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
+  static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
+
   static void init_thread_fpu_state();
   static int  get_fpu_control_word();
   static void set_fpu_control_word(int fpu_control);
@@ -209,39 +213,27 @@
   // for LinuxThreads are no longer needed.
   class SuspendResume {
   private:
-    volatile int _suspend_action;
+    volatile int  _suspend_action;
+    volatile jint _state;
+  public:
     // values for suspend_action:
-    #define SR_NONE               (0x00)
-    #define SR_SUSPEND            (0x01)  // suspend request
-    #define SR_CONTINUE           (0x02)  // resume request
+    enum {
+      SR_NONE              = 0x00,
+      SR_SUSPEND           = 0x01,  // suspend request
+      SR_CONTINUE          = 0x02,  // resume request
+      SR_SUSPENDED         = 0x20   // values for _state: + SR_NONE
+    };
 
-    volatile jint _state;
-    // values for _state: + SR_NONE
-    #define SR_SUSPENDED          (0x20)
-  public:
     SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; }
 
     int suspend_action() const     { return _suspend_action; }
     void set_suspend_action(int x) { _suspend_action = x;    }
 
     // atomic updates for _state
-    void set_suspended()           {
-      jint temp, temp2;
-      do {
-        temp = _state;
-        temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
-      } while (temp2 != temp);
-    }
-    void clear_suspended()        {
-      jint temp, temp2;
-      do {
-        temp = _state;
-        temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
-      } while (temp2 != temp);
-    }
+    inline void set_suspended();
+    inline void clear_suspended();
     bool is_suspended()            { return _state & SR_SUSPENDED;       }
 
-    #undef SR_SUSPENDED
   };
 
 private:
--- a/src/os/linux/vm/os_linux.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/linux/vm/os_linux.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,6 @@
 #ifndef OS_LINUX_VM_OS_LINUX_INLINE_HPP
 #define OS_LINUX_VM_OS_LINUX_INLINE_HPP
 
-#include "runtime/atomic.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 
@@ -288,4 +287,21 @@
                             const char* optval, socklen_t optlen) {
   return ::setsockopt(fd, level, optname, optval, optlen);
 }
+
+inline void os::Linux::SuspendResume::set_suspended() {
+  jint temp, temp2;
+  do {
+    temp = _state;
+    temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
+  } while (temp2 != temp);
+}
+
+inline void os::Linux::SuspendResume::clear_suspended()        {
+  jint temp, temp2;
+  do {
+    temp = _state;
+    temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
+  } while (temp2 != temp);
+}
+
 #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP
--- a/src/os/linux/vm/perfMemory_linux.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/linux/vm/perfMemory_linux.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -672,15 +672,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -828,7 +828,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -899,9 +899,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/posix/launcher/launcher.script	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/posix/launcher/launcher.script	Mon Apr 15 08:51:19 2013 +0200
@@ -199,7 +199,7 @@
 	rm -f $GDBSCR
         ;;
     dbx)
-        $DBX -s $MYDIR/.dbxrc $LAUNCHER $JPARAMS
+        $DBX -s $HOME/.dbxrc $LAUNCHER $JPARMS
         ;;
     valgrind)
         echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap
--- a/src/os/posix/vm/os_posix.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/posix/vm/os_posix.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -188,4 +188,66 @@
   st->cr();
 }
 
+bool os::has_allocatable_memory_limit(julong* limit) {
+  struct rlimit rlim;
+  int getrlimit_res = getrlimit(RLIMIT_AS, &rlim);
+  // if there was an error when calling getrlimit, assume that there is no limitation
+  // on virtual memory.
+  bool result;
+  if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) {
+    result = false;
+  } else {
+    *limit = (julong)rlim.rlim_cur;
+    result = true;
+  }
+#ifdef _LP64
+  return result;
+#else
+  // arbitrary virtual space limit for 32 bit Unices found by testing. If
+  // getrlimit above returned a limit, bound it with this limit. Otherwise
+  // directly use it.
+  const julong max_virtual_limit = (julong)3800*M;
+  if (result) {
+    *limit = MIN2(*limit, max_virtual_limit);
+  } else {
+    *limit = max_virtual_limit;
+  }
 
+  // bound by actually allocatable memory. The algorithm uses two bounds, an
+  // upper and a lower limit. The upper limit is the current highest amount of
+  // memory that could not be allocated, the lower limit is the current highest
+  // amount of memory that could be allocated.
+  // The algorithm iteratively refines the result by halving the difference
+  // between these limits, updating either the upper limit (if that value could
+  // not be allocated) or the lower limit (if the that value could be allocated)
+  // until the difference between these limits is "small".
+
+  // the minimum amount of memory we care about allocating.
+  const julong min_allocation_size = M;
+
+  julong upper_limit = *limit;
+
+  // first check a few trivial cases
+  if (is_allocatable(upper_limit) || (upper_limit <= min_allocation_size)) {
+    *limit = upper_limit;
+  } else if (!is_allocatable(min_allocation_size)) {
+    // we found that not even min_allocation_size is allocatable. Return it
+    // anyway. There is no point to search for a better value any more.
+    *limit = min_allocation_size;
+  } else {
+    // perform the binary search.
+    julong lower_limit = min_allocation_size;
+    while ((upper_limit - lower_limit) > min_allocation_size) {
+      julong temp_limit = ((upper_limit - lower_limit) / 2) + lower_limit;
+      temp_limit = align_size_down_(temp_limit, min_allocation_size);
+      if (is_allocatable(temp_limit)) {
+        lower_limit = temp_limit;
+      } else {
+        upper_limit = temp_limit;
+      }
+    }
+    *limit = lower_limit;
+  }
+  return true;
+#endif
+}
--- a/src/os/solaris/vm/os_solaris.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/solaris/vm/os_solaris.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -476,24 +476,6 @@
    return Solaris::physical_memory();
 }
 
-julong os::allocatable_physical_memory(julong size) {
-#ifdef _LP64
-   return size;
-#else
-   julong result = MIN2(size, (julong)3835*M);
-   if (!is_allocatable(result)) {
-     // Memory allocations will be aligned but the alignment
-     // is not known at this point.  Alignments will
-     // be at most to LargePageSizeInBytes.  Protect
-     // allocations from alignments up to illegal
-     // values. If at this point 2G is illegal.
-     julong reasonable_size = (julong)2*G - 2 * LargePageSizeInBytes;
-     result =  MIN2(size, reasonable_size);
-   }
-   return result;
-#endif
-}
-
 static hrtime_t first_hrtime = 0;
 static const hrtime_t hrtime_hz = 1000*1000*1000;
 const int LOCK_BUSY = 1;
@@ -1903,6 +1885,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // really shouldn't be NULL but what the heck, check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -2945,7 +2930,7 @@
   while (p < (uint64_t)end) {
     addrs[0] = p;
     size_t addrs_count = 1;
-    while (addrs_count < MAX_MEMINFO_CNT && addrs[addrs_count - 1] < (uint64_t)end) {
+    while (addrs_count < MAX_MEMINFO_CNT && addrs[addrs_count - 1] + page_size < (uint64_t)end) {
       addrs[addrs_count] = addrs[addrs_count - 1] + page_size;
       addrs_count++;
     }
@@ -3420,13 +3405,25 @@
   if ((retAddr != NULL) && UseNUMAInterleaving) {
     numa_make_global(retAddr, size);
   }
+
+  // The memory is committed
+  address pc = CALLER_PC;
+  MemTracker::record_virtual_memory_reserve((address)retAddr, size, pc);
+  MemTracker::record_virtual_memory_commit((address)retAddr, size, pc);
+
   return retAddr;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
   // detaching the SHM segment will also delete it, see reserve_memory_special()
   int rslt = shmdt(base);
-  return rslt == 0;
+  if (rslt == 0) {
+    MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+    MemTracker::record_virtual_memory_release((address)base, bytes);
+    return true;
+  } else {
+   return false;
+  }
 }
 
 size_t os::large_page_size() {
@@ -5793,16 +5790,6 @@
 
 //---------------------------------------------------------------------------------
 
-static address same_page(address x, address y) {
-  intptr_t page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -5828,8 +5815,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
--- a/src/os/solaris/vm/os_solaris.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/solaris/vm/os_solaris.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,6 @@
 #ifndef OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
 #define OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
 
-#include "runtime/atomic.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 
--- a/src/os/solaris/vm/perfMemory_solaris.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/solaris/vm/perfMemory_solaris.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -687,15 +687,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -843,7 +843,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -914,9 +914,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/windows/vm/decoder_windows.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/windows/vm/decoder_windows.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "prims/jvm.h"
+#include "runtime/arguments.hpp"
 #include "decoder_windows.hpp"
 
 WindowsDecoder::WindowsDecoder() {
--- a/src/os/windows/vm/os_windows.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/windows/vm/os_windows.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -60,6 +60,7 @@
 #include "runtime/threadCritical.hpp"
 #include "runtime/timer.hpp"
 #include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
@@ -685,12 +686,17 @@
   return win32::physical_memory();
 }
 
-julong os::allocatable_physical_memory(julong size) {
+bool os::has_allocatable_memory_limit(julong* limit) {
+  MEMORYSTATUSEX ms;
+  ms.dwLength = sizeof(ms);
+  GlobalMemoryStatusEx(&ms);
 #ifdef _LP64
-  return size;
+  *limit = (julong)ms.ullAvailVirtual;
+  return true;
 #else
   // Limit to 1400m because of the 2gb address space wall
-  return MIN2(size, (julong)1400*M);
+  *limit = MIN2((julong)1400*M, (julong)ms.ullAvailVirtual);
+  return true;
 #endif
 }
 
@@ -1176,6 +1182,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       char* path = pelements[i];
       // Really shouldn't be NULL, but check can't hurt
@@ -2852,7 +2861,7 @@
                                 PAGE_READWRITE);
   // If reservation failed, return NULL
   if (p_buf == NULL) return NULL;
-
+  MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
   os::release_memory(p_buf, bytes + chunk_size);
 
   // we still need to round up to a page boundary (in case we are using large pages)
@@ -2914,6 +2923,11 @@
       if (next_alloc_addr > p_buf) {
         // Some memory was committed so release it.
         size_t bytes_to_release = bytes - bytes_remaining;
+        // NMT has yet to record any individual blocks, so it
+        // need to create a dummy 'reserve' record to match
+        // the release.
+        MemTracker::record_virtual_memory_reserve((address)p_buf,
+          bytes_to_release, CALLER_PC);
         os::release_memory(p_buf, bytes_to_release);
       }
 #ifdef ASSERT
@@ -2925,10 +2939,19 @@
 #endif
       return NULL;
     }
+
     bytes_remaining -= bytes_to_rq;
     next_alloc_addr += bytes_to_rq;
     count++;
   }
+  // Although the memory is allocated individually, it is returned as one.
+  // NMT records it as one block.
+  address pc = CALLER_PC;
+  MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, pc);
+  if ((flags & MEM_COMMIT) != 0) {
+    MemTracker::record_virtual_memory_commit((address)p_buf, bytes, pc);
+  }
+
   // made it this far, success
   return p_buf;
 }
@@ -3115,11 +3138,20 @@
     // normal policy just allocate it all at once
     DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
     char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot);
+    if (res != NULL) {
+      address pc = CALLER_PC;
+      MemTracker::record_virtual_memory_reserve((address)res, bytes, pc);
+      MemTracker::record_virtual_memory_commit((address)res, bytes, pc);
+    }
+
     return res;
   }
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
+  assert(base != NULL, "Sanity check");
+  // Memory allocated via reserve_memory_special() is committed
+  MemTracker::record_virtual_memory_uncommit((address)base, bytes);
   return release_memory(base, bytes);
 }
 
@@ -3760,6 +3792,8 @@
   }
 }
 
+static jint initSock();
+
 // this is called _after_ the global arguments have been parsed
 jint os::init_2(void) {
   // Allocate a single page and mark it as readable for safepoint polling
@@ -3890,6 +3924,10 @@
     if (!success) UseNUMAInterleaving = false;
   }
 
+  if (initSock() != JNI_OK) {
+    return JNI_ERR;
+  }
+
   return JNI_OK;
 }
 
@@ -4886,42 +4924,24 @@
 // We don't build a headless jre for Windows
 bool os::is_headless_jre() { return false; }
 
-
-typedef CRITICAL_SECTION mutex_t;
-#define mutexInit(m)    InitializeCriticalSection(m)
-#define mutexDestroy(m) DeleteCriticalSection(m)
-#define mutexLock(m)    EnterCriticalSection(m)
-#define mutexUnlock(m)  LeaveCriticalSection(m)
-
-static bool sock_initialized = FALSE;
-static mutex_t sockFnTableMutex;
-
-static void initSock() {
+static jint initSock() {
   WSADATA wsadata;
 
   if (!os::WinSock2Dll::WinSock2Available()) {
-    jio_fprintf(stderr, "Could not load Winsock 2 (error: %d)\n",
+    jio_fprintf(stderr, "Could not load Winsock (error: %d)\n",
       ::GetLastError());
-    return;
-  }
-  if (sock_initialized == TRUE) return;
-
-  ::mutexInit(&sockFnTableMutex);
-  ::mutexLock(&sockFnTableMutex);
-  if (os::WinSock2Dll::WSAStartup(MAKEWORD(1,1), &wsadata) != 0) {
-      jio_fprintf(stderr, "Could not initialize Winsock\n");
-  }
-  sock_initialized = TRUE;
-  ::mutexUnlock(&sockFnTableMutex);
+    return JNI_ERR;
+  }
+
+  if (os::WinSock2Dll::WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {
+    jio_fprintf(stderr, "Could not initialize Winsock (error: %d)\n",
+      ::GetLastError());
+    return JNI_ERR;
+  }
+  return JNI_OK;
 }
 
 struct hostent* os::get_host_by_name(char* name) {
-  if (!sock_initialized) {
-    initSock();
-  }
-  if (!os::WinSock2Dll::WinSock2Available()) {
-    return NULL;
-  }
   return (struct hostent*)os::WinSock2Dll::gethostbyname(name);
 }
 
--- a/src/os/windows/vm/os_windows.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/windows/vm/os_windows.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,6 @@
 #ifndef OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
 #define OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
 
-#include "runtime/atomic.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 
--- a/src/os/windows/vm/perfMemory_windows.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os/windows/vm/perfMemory_windows.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1581,7 +1581,7 @@
   ResourceMark rm;
 
   void *mapAddress = 0;
-  size_t size;
+  size_t size = 0;
   HANDLE fmh;
   DWORD ofm_access;
   DWORD mv_access;
@@ -1652,9 +1652,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(rfilename, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   // Open the file mapping object with the given name
   fmh = open_sharedmem_object(robjectname, ofm_access, CHECK);
 
--- a/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
 #define OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
 
-#include "orderAccess_bsd_x86.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
--- a/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -55,20 +55,6 @@
   // adding a syntax that specifies the sizes of fields in an order,
   // so that the adlc can build the emit functions automagically
 
-  enc_class Java_To_Runtime(method meth) %{
-    // No relocation needed
-
-    // movq r10, <meth>
-    emit_opcode(cbuf, Assembler::REX_WB);
-    emit_opcode(cbuf, 0xB8 | (R10_enc - 8));
-    emit_d64(cbuf, (int64_t) $meth$$method);
-
-    // call (r10)
-    emit_opcode(cbuf, Assembler::REX_B);
-    emit_opcode(cbuf, 0xFF);
-    emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
-  %}
-
 %}
 
 
@@ -76,8 +62,4 @@
 
 source %{
 
-int MachCallRuntimeNode::ret_addr_offset() {
-  return 13; // movq r10,#addr; callq (r10)
-}
-
 %}
--- a/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -46,7 +46,7 @@
 
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx, HeapBaseMinAddress,      2*G);
 
 #endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
--- a/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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,8 +25,9 @@
 #ifndef OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
 #define OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
 
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
 
 // Implementation of class OrderAccess.
--- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -516,7 +516,7 @@
         // here if the underlying file has been truncated.
         // Do not crash the VM in such a case.
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
-        nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
+        nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
           stub = StubRoutines::handler_for_unsafe_access();
         }
--- a/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -26,7 +26,6 @@
 #ifndef OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
 #define OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
 
-#include "orderAccess_bsd_zero.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_zero.hpp"
--- a/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -41,7 +41,7 @@
 define_pd_global(intx,  CompilerThreadStackSize, 0);
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx, HeapBaseMinAddress,      2*G);
 
 #endif // OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
--- a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP
 #define OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP
 
-#include "orderAccess_linux_sparc.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_sparc.hpp"
--- a/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
 define_pd_global(uintx, JVMInvokeMethodSlack,    12288);
 define_pd_global(intx, CompilerThreadStackSize,  0);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx, HeapBaseMinAddress,      CONST64(4)*G);
 
 #endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -410,6 +410,11 @@
       // to handle_unexpected_exception way down below.
       thread->disable_stack_red_zone();
       tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+
+      // This is a likely cause, but hard to verify. Let's just print
+      // it as a hint.
+      tty->print_raw_cr("Please check if any of your loaded .so files has "
+                        "enabled executable stack (see man page execstack(8))");
     } else {
       // Accessing stack address below sp may cause SEGV if current
       // thread has MAP_GROWSDOWN stack. This should only happen when
--- a/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP
 #define OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP
 
-#include "orderAccess_linux_x86.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
--- a/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -44,7 +44,7 @@
 
 define_pd_global(uintx,JVMInvokeMethodSlack,     8192);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx,HeapBaseMinAddress,       2*G);
 
 #endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP
--- a/src/os_cpu/linux_x86/vm/linux_x86_64.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_x86/vm/linux_x86_64.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -55,20 +55,6 @@
   // adding a syntax that specifies the sizes of fields in an order,
   // so that the adlc can build the emit functions automagically
 
-  enc_class Java_To_Runtime(method meth) %{
-    // No relocation needed
-
-    // movq r10, <meth>
-    emit_opcode(cbuf, Assembler::REX_WB);
-    emit_opcode(cbuf, 0xB8 | (R10_enc - 8));
-    emit_d64(cbuf, (int64_t) $meth$$method);
-
-    // call (r10)
-    emit_opcode(cbuf, Assembler::REX_B);
-    emit_opcode(cbuf, 0xFF);
-    emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
-  %}
-
 %}
 
 
@@ -76,8 +62,4 @@
 
 source %{
 
-int MachCallRuntimeNode::ret_addr_offset() {
-  return 13; // movq r10,#addr; callq (r10)
-}
-
 %}
--- a/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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,8 +25,9 @@
 #ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
 #define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
 
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
 
 // Implementation of class OrderAccess.
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -305,6 +305,11 @@
           // to handle_unexpected_exception way down below.
           thread->disable_stack_red_zone();
           tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+
+          // This is a likely cause, but hard to verify. Let's just print
+          // it as a hint.
+          tty->print_raw_cr("Please check if any of your loaded .so files has "
+                            "enabled executable stack (see man page execstack(8))");
         } else {
           // Accessing stack address below sp may cause SEGV if current
           // thread has MAP_GROWSDOWN stack. This should only happen when
@@ -335,7 +340,7 @@
         // here if the underlying file has been truncated.
         // Do not crash the VM in such a case.
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
-        nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
+        nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
           stub = StubRoutines::handler_for_unsafe_access();
         }
--- a/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -26,7 +26,6 @@
 #ifndef OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_INLINE_HPP
 #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_INLINE_HPP
 
-#include "orderAccess_linux_zero.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_zero.hpp"
--- a/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -41,7 +41,7 @@
 define_pd_global(intx,  CompilerThreadStackSize, 0);
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx, HeapBaseMinAddress,      2*G);
 
 #endif // OS_CPU_LINUX_ZERO_VM_GLOBALS_LINUX_ZERO_HPP
--- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP
 #define OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP
 
-#include "orderAccess_solaris_sparc.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_sparc.hpp"
--- a/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
 define_pd_global(uintx, JVMInvokeMethodSlack,    12288);
 define_pd_global(intx, CompilerThreadStackSize,  0);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 #ifdef _LP64
 define_pd_global(uintx, HeapBaseMinAddress,      CONST64(4)*G);
 #else
--- a/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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 @@
 #ifndef OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP
 #define OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP
 
+#include "runtime/atomic.inline.hpp"
 #include "runtime/orderAccess.hpp"
 #include "vm_version_sparc.hpp"
 
--- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_INLINE_HPP
 #define OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_INLINE_HPP
 
-#include "orderAccess_solaris_x86.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
--- a/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -43,7 +43,7 @@
 
 define_pd_global(intx, CompilerThreadStackSize,  0);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx,HeapBaseMinAddress,       256*M);
 
 #endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP
--- a/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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,7 +25,7 @@
 #ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
 #define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
 
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -54,39 +54,10 @@
   // main source block for now.  In future, we can generalize this by
   // adding a syntax that specifies the sizes of fields in an order,
   // so that the adlc can build the emit functions automagically
-
-  enc_class Java_To_Runtime(method meth) %{
-    // No relocation needed
-
-    // movq r10, <meth>
-    emit_opcode(cbuf, Assembler::REX_WB);
-    emit_opcode(cbuf, 0xB8 | (R10_enc - 8));
-    emit_d64(cbuf, (int64_t) $meth$$method);
-
-    // call (r10)
-    emit_opcode(cbuf, Assembler::REX_B);
-    emit_opcode(cbuf, 0xFF);
-    emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
-  %}
-
-  enc_class post_call_verify_mxcsr %{
-    MacroAssembler _masm(&cbuf);
-    if (RestoreMXCSROnJNICalls) {
-      __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std()));
-    }
-    else if (CheckJNICalls) {
-      __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry())));
-    }
-  %}
 %}
 
 
 // Platform dependent source
 
 source %{
-
-int MachCallRuntimeNode::ret_addr_offset() {
-  return 13; // movq r10,#addr; callq (r10)
-}
-
 %}
--- a/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, 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,7 +25,6 @@
 #ifndef OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_INLINE_HPP
 #define OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_INLINE_HPP
 
-#include "orderAccess_windows_x86.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
--- a/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -45,7 +45,7 @@
 
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
-// Used on 64 bit platforms for UseCompressedOops base address or CDS
+// Used on 64 bit platforms for UseCompressedOops base address
 define_pd_global(uintx, HeapBaseMinAddress,      2*G);
 
 #endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP
--- a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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,12 +25,11 @@
 #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
 #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
 
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
 #include "vm_version_x86.hpp"
 
-#pragma warning(disable: 4035) // Disables warnings reporting missing return statement
-
 // Implementation of class OrderAccess.
 
 inline void OrderAccess::loadload()   { acquire(); }
@@ -214,6 +213,4 @@
 #endif // AMD64
 }
 
-#pragma warning(default: 4035) // Enables warnings reporting missing return statement
-
 #endif // OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
--- a/src/os_cpu/windows_x86/vm/windows_x86_64.ad	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/os_cpu/windows_x86/vm/windows_x86_64.ad	Mon Apr 15 08:51:19 2013 +0200
@@ -53,30 +53,11 @@
   // adding a syntax that specifies the sizes of fields in an order,
   // so that the adlc can build the emit functions automagically
 
-  enc_class Java_To_Runtime (method meth) %{    // CALL Java_To_Runtime
-    // No relocation needed
+%}
+
 
-    // movq r10, <meth>
-    emit_opcode(cbuf, Assembler::REX_WB);
-    emit_opcode(cbuf, 0xB8 | (R10_enc - 8));
-    emit_d64(cbuf, (int64_t) $meth$$method);
+// Platform dependent source
 
-    // call (r10)
-    emit_opcode(cbuf, Assembler::REX_B);
-    emit_opcode(cbuf, 0xFF);
-    emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
-  %}
+source %{
 
 %}
-
-//
-// Platform dependent source
-//
-source %{
-
-int MachCallRuntimeNode::ret_addr_offset()
-{
-  return 13; // movq r10,#addr; callq (r10)
-}
-
-%}
--- a/src/share/tools/ProjectCreator/BuildConfig.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/tools/ProjectCreator/BuildConfig.java	Mon Apr 15 08:51:19 2013 +0200
@@ -635,36 +635,6 @@
     }
 }
 
-class KernelDebugConfig extends GenericDebugConfig {
-    String getOptFlag() {
-        return getCI().getNoOptFlag();
-    }
-
-    KernelDebugConfig() {
-        initNames("kernel", "debug", "jvm.dll");
-        init(getIncludes(), getDefines());
-    }
-}
-
-
-class KernelFastDebugConfig extends GenericDebugConfig {
-    String getOptFlag() {
-        return getCI().getOptFlag();
-    }
-
-    KernelFastDebugConfig() {
-        initNames("kernel", "fastdebug", "jvm.dll");
-        init(getIncludes(), getDefines());
-    }
-}
-
-
-class KernelProductConfig extends ProductConfig {
-    KernelProductConfig() {
-        initNames("kernel", "product", "jvm.dll");
-        init(getIncludes(), getDefines());
-    }
-}
 
 abstract class CompilerInterface {
     abstract Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir);
--- a/src/share/tools/ProjectCreator/WinGammaPlatform.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/tools/ProjectCreator/WinGammaPlatform.java	Mon Apr 15 08:51:19 2013 +0200
@@ -568,12 +568,6 @@
         allConfigs.add(new CoreFastDebugConfig());
         allConfigs.add(new CoreProductConfig());
 
-        if (platform.equals("Win32")) {
-            allConfigs.add(new KernelDebugConfig());
-            allConfigs.add(new KernelFastDebugConfig());
-            allConfigs.add(new KernelProductConfig());
-        }
-
         return allConfigs;
     }
 
--- a/src/share/tools/launcher/wildcard.c	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/tools/launcher/wildcard.c	Mon Apr 15 08:51:19 2013 +0200
@@ -368,8 +368,10 @@
     const char *basename;
     FileList fl = FileList_new(16);
     WildcardIterator it = WildcardIterator_for(wildcard);
-    if (it == NULL)
+    if (it == NULL) {
+        FileList_free(fl);
         return NULL;
+    }
     while ((basename = WildcardIterator_next(it)) != NULL)
         if (isJarFileName(basename))
             FileList_add(fl, wildcardConcat(wildcard, basename));
--- a/src/share/vm/adlc/archDesc.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/adlc/archDesc.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -832,6 +832,7 @@
     int         length  = (int)strlen(rc_name) + (int)strlen(mask) + 5;
     char       *regMask = new char[length];
     sprintf(regMask,"%s%s()", rc_name, mask);
+    delete[] rc_name;
     return regMask;
   }
 }
--- a/src/share/vm/adlc/dfa.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/adlc/dfa.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -191,12 +191,19 @@
 // Macro equivalent to: _kids[0]->valid(FOO) && _kids[1]->valid(BAR)
 //
 static void child_test(FILE *fp, MatchList &mList) {
-  if( mList._lchild )           // If left child, check it
-    fprintf(fp, "STATE__VALID_CHILD(_kids[0], %s)", ArchDesc::getMachOperEnum(mList._lchild));
-  if( mList._lchild && mList._rchild )      // If both, add the "&&"
-    fprintf(fp, " && " );
-  if( mList._rchild )           // If right child, check it
-    fprintf(fp, "STATE__VALID_CHILD(_kids[1], %s)", ArchDesc::getMachOperEnum(mList._rchild));
+  if (mList._lchild) { // If left child, check it
+    const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild);
+    fprintf(fp, "STATE__VALID_CHILD(_kids[0], %s)", lchild_to_upper);
+    delete[] lchild_to_upper;
+  }
+  if (mList._lchild && mList._rchild) { // If both, add the "&&"
+    fprintf(fp, " && ");
+  }
+  if (mList._rchild) { // If right child, check it
+    const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild);
+    fprintf(fp, "STATE__VALID_CHILD(_kids[1], %s)", rchild_to_upper);
+    delete[] rchild_to_upper;
+  }
 }
 
 //---------------------------calc_cost-----------------------------------------
@@ -206,13 +213,17 @@
 Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status) {
   fprintf(fp, "%sunsigned int c = ", spaces);
   Expr *c = new Expr("0");
-  if (mList._lchild ) {                   // If left child, add it in
-    sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", ArchDesc::getMachOperEnum(mList._lchild));
+  if (mList._lchild) { // If left child, add it in
+    const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild);
+    sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper);
     c->add(Expr::buffer());
+    delete[] lchild_to_upper;
 }
-  if (mList._rchild) {                    // If right child, add it in
-    sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", ArchDesc::getMachOperEnum(mList._rchild));
+  if (mList._rchild) { // If right child, add it in
+    const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild);
+    sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper);
     c->add(Expr::buffer());
+    delete[] rchild_to_upper;
   }
   // Add in cost of this rule
   const char *mList_cost = mList.get_cost();
@@ -232,15 +243,17 @@
   fprintf(fp, "%s", spaces4);
   // Only generate child tests if this is not a leaf node
   bool has_child_constraints = mList._lchild || mList._rchild;
-  const char *predicate_test        = mList.get_pred();
-  if( has_child_constraints || predicate_test ) {
+  const char *predicate_test = mList.get_pred();
+  if (has_child_constraints || predicate_test) {
     // Open the child-and-predicate-test braces
     fprintf(fp, "if( ");
     status.set_constraint(hasConstraint);
     child_test(fp, mList);
     // Only generate predicate test if one exists for this match
-    if( predicate_test ) {
-      if( has_child_constraints ) { fprintf(fp," &&\n"); }
+    if (predicate_test) {
+      if (has_child_constraints) {
+        fprintf(fp," &&\n");
+      }
       fprintf(fp, "%s  %s", spaces6, predicate_test);
     }
     // End of outer tests
--- a/src/share/vm/adlc/output_c.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/adlc/output_c.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -63,11 +63,10 @@
     RegDef *reg_def = NULL;
     RegDef *next = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
-      fprintf(fp,"  \"%s\"%s\n",
-                 reg_def->_regname, comma );
+      fprintf(fp,"  \"%s\"%s\n", reg_def->_regname, comma);
     }
 
     // Finish defining enumeration
@@ -79,10 +78,10 @@
     reg_def = NULL;
     next = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
-      fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma );
+      fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma);
     }
     // Finish defining array
     fprintf(fp,"\t};\n");
@@ -104,19 +103,17 @@
     RegDef *reg_def = NULL;
     RegDef *next    = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char* register_encode = reg_def->register_encode();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
       int encval;
       if (!ADLParser::is_int_token(register_encode, encval)) {
-        fprintf(fp,"  %s%s  // %s\n",
-                register_encode, comma, reg_def->_regname );
+        fprintf(fp,"  %s%s  // %s\n", register_encode, comma, reg_def->_regname);
       } else {
         // Output known constants in hex char format (backward compatibility).
         assert(encval < 256, "Exceeded supported width for register encoding");
-        fprintf(fp,"  (unsigned char)'\\x%X'%s  // %s\n",
-                encval,          comma, reg_def->_regname );
+        fprintf(fp,"  (unsigned char)'\\x%X'%s  // %s\n", encval, comma, reg_def->_regname);
       }
     }
     // Finish defining enumeration
@@ -133,9 +130,10 @@
     fprintf(fp,"// Enumeration of register class names\n");
     fprintf(fp, "enum machRegisterClass {\n");
     registers->_rclasses.reset();
-    for( const char *class_name = NULL;
-         (class_name = registers->_rclasses.iter()) != NULL; ) {
-      fprintf(fp,"  %s,\n", toUpper( class_name ));
+    for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) {
+      const char * class_name_to_upper = toUpper(class_name);
+      fprintf(fp,"  %s,\n", class_name_to_upper);
+      delete[] class_name_to_upper;
     }
     // Finish defining enumeration
     fprintf(fp, "  _last_Mach_Reg_Class\n");
@@ -148,7 +146,7 @@
 void ArchDesc::declare_register_masks(FILE *fp_hpp) {
   const char  *rc_name;
 
-  if( _register ) {
+  if (_register) {
     // Build enumeration of user-defined register classes.
     defineRegClassEnum(fp_hpp, _register);
 
@@ -156,24 +154,27 @@
     fprintf(fp_hpp,"\n");
     fprintf(fp_hpp,"// Register masks, one for each register class.\n");
     _register->_rclasses.reset();
-    for( rc_name = NULL;
-         (rc_name = _register->_rclasses.iter()) != NULL; ) {
-      const char *prefix    = "";
-      RegClass   *reg_class = _register->getRegClass(rc_name);
-      assert( reg_class, "Using an undefined register class");
+    for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
+      const char *prefix = "";
+      RegClass *reg_class = _register->getRegClass(rc_name);
+      assert(reg_class, "Using an undefined register class");
+
+      const char* rc_name_to_upper = toUpper(rc_name);
 
       if (reg_class->_user_defined == NULL) {
-        fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) );
-        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ));
+        fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix,  rc_name_to_upper);
+        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
       } else {
-        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined);
+        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined);
       }
 
-      if( reg_class->_stack_or_reg ) {
+      if (reg_class->_stack_or_reg) {
         assert(reg_class->_user_defined == NULL, "no user defined reg class here");
-        fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) );
-        fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) );
+        fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper);
+        fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
       }
+      delete[] rc_name_to_upper;
+
     }
   }
 }
@@ -183,34 +184,41 @@
 void ArchDesc::build_register_masks(FILE *fp_cpp) {
   const char  *rc_name;
 
-  if( _register ) {
+  if (_register) {
     // Generate a list of register masks, one for each class.
     fprintf(fp_cpp,"\n");
     fprintf(fp_cpp,"// Register masks, one for each register class.\n");
     _register->_rclasses.reset();
-    for( rc_name = NULL;
-         (rc_name = _register->_rclasses.iter()) != NULL; ) {
-      const char *prefix    = "";
-      RegClass   *reg_class = _register->getRegClass(rc_name);
-      assert( reg_class, "Using an undefined register class");
-
-      if (reg_class->_user_defined != NULL) continue;
+    for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
+      const char *prefix = "";
+      RegClass *reg_class = _register->getRegClass(rc_name);
+      assert(reg_class, "Using an undefined register class");
+
+      if (reg_class->_user_defined != NULL) {
+        continue;
+      }
 
       int len = RegisterForm::RegMask_Size();
-      fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) );
-      { int i;
-        for( i = 0; i < len-1; i++ )
-          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false));
-        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false));
+      const char* rc_name_to_upper = toUpper(rc_name);
+      fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper);
+
+      {
+        int i;
+        for(i = 0; i < len - 1; i++) {
+          fprintf(fp_cpp," 0x%x,", reg_class->regs_in_word(i, false));
+        }
+        fprintf(fp_cpp," 0x%x );\n", reg_class->regs_in_word(i, false));
       }
 
-      if( reg_class->_stack_or_reg ) {
+      if (reg_class->_stack_or_reg) {
         int i;
-        fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) );
-        for( i = 0; i < len-1; i++ )
-          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true));
-        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true));
+        fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper);
+        for(i = 0; i < len - 1; i++) {
+          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i, true));
+        }
+        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i, true));
       }
+      delete[] rc_name_to_upper;
     }
   }
 }
@@ -2676,7 +2684,9 @@
       if (strcmp(first_reg_class, "stack_slots") == 0) {
         fprintf(fp,"  return &(Compile::current()->FIRST_STACK_mask());\n");
       } else {
-        fprintf(fp,"  return &%s_mask();\n", toUpper(first_reg_class));
+        const char* first_reg_class_to_upper = toUpper(first_reg_class);
+        fprintf(fp,"  return &%s_mask();\n", first_reg_class_to_upper);
+        delete[] first_reg_class_to_upper;
       }
     } else {
       // Build a switch statement to return the desired mask.
@@ -2688,7 +2698,9 @@
         if( !strcmp(reg_class, "stack_slots") ) {
           fprintf(fp, "  case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index);
         } else {
-          fprintf(fp, "  case %d: return &%s_mask();\n", index, toUpper(reg_class));
+          const char* reg_class_to_upper = toUpper(reg_class);
+          fprintf(fp, "  case %d: return &%s_mask();\n", index, reg_class_to_upper);
+          delete[] reg_class_to_upper;
         }
       }
       fprintf(fp,"  }\n");
--- a/src/share/vm/adlc/output_h.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/adlc/output_h.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -2069,9 +2069,21 @@
   void closing()     { fprintf(_cpp, "  _LAST_MACH_OPER\n");
                        OutputMap::closing();
   }
-  void map(OpClassForm &opc)  { fprintf(_cpp, "  %s", _AD.machOperEnum(opc._ident) ); }
-  void map(OperandForm &oper) { fprintf(_cpp, "  %s", _AD.machOperEnum(oper._ident) ); }
-  void map(char        *name) { fprintf(_cpp, "  %s", _AD.machOperEnum(name)); }
+  void map(OpClassForm &opc)  {
+    const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident);
+    fprintf(_cpp, "  %s", opc_ident_to_upper);
+    delete[] opc_ident_to_upper;
+  }
+  void map(OperandForm &oper) {
+    const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident);
+    fprintf(_cpp, "  %s", oper_ident_to_upper);
+    delete[] oper_ident_to_upper;
+  }
+  void map(char *name) {
+    const char* name_to_upper = _AD.machOperEnum(name);
+    fprintf(_cpp, "  %s", name_to_upper);
+    delete[] name_to_upper;
+  }
 
   bool do_instructions()      { return false; }
   void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); }
--- a/src/share/vm/asm/assembler.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/asm/assembler.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -284,15 +284,19 @@
   DelayedConstant::update_all();
 }
 
-
-
-
 void AbstractAssembler::block_comment(const char* comment) {
   if (sect() == CodeBuffer::SECT_INSTS) {
     code_section()->outer()->block_comment(offset(), comment);
   }
 }
 
+const char* AbstractAssembler::code_string(const char* str) {
+  if (sect() == CodeBuffer::SECT_INSTS || sect() == CodeBuffer::SECT_STUBS) {
+    return code_section()->outer()->code_string(str);
+  }
+  return NULL;
+}
+
 bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
   // Exception handler checks the nmethod's implicit null checks table
   // only when this method returns false.
--- a/src/share/vm/asm/assembler.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/asm/assembler.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -336,6 +336,8 @@
   // along with the disassembly when printing nmethods.  Currently
   // only supported in the instruction section of the code buffer.
   void block_comment(const char* comment);
+  // Copy str to a buffer that has the same lifetime as the CodeBuffer
+  const char* code_string(const char* str);
 
   // Label functions
   void bind(Label& L); // binds an unbound label L to the current code position
--- a/src/share/vm/asm/codeBuffer.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/asm/codeBuffer.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -703,8 +703,8 @@
   this->compute_final_layout(&dest);
   relocate_code_to(&dest);
 
-  // transfer comments from buffer to blob
-  dest_blob->set_comments(_comments);
+  // transfer strings and comments from buffer to blob
+  dest_blob->set_strings(_strings);
 
   // Done moving code bytes; were they the right size?
   assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
@@ -1003,58 +1003,78 @@
 
 
 void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
-  _comments.add_comment(offset, comment);
+  _strings.add_comment(offset, comment);
+}
+
+const char* CodeBuffer::code_string(const char* str) {
+  return _strings.add_string(str);
 }
 
-class CodeComment: public CHeapObj<mtCode> {
+class CodeString: public CHeapObj<mtCode> {
  private:
-  friend class CodeComments;
+  friend class CodeStrings;
+  const char * _string;
+  CodeString*  _next;
   intptr_t     _offset;
-  const char * _comment;
-  CodeComment* _next;
 
-  ~CodeComment() {
+  ~CodeString() {
     assert(_next == NULL, "wrong interface for freeing list");
-    os::free((void*)_comment, mtCode);
-  }
-
- public:
-  CodeComment(intptr_t offset, const char * comment) {
-    _offset = offset;
-    _comment = os::strdup(comment, mtCode);
-    _next = NULL;
+    os::free((void*)_string, mtCode);
   }
 
-  intptr_t     offset()  const { return _offset;  }
-  const char * comment() const { return _comment; }
-  CodeComment* next()          { return _next; }
-
-  void set_next(CodeComment* next) { _next = next; }
+  bool is_comment() const { return _offset >= 0; }
 
-  CodeComment* find(intptr_t offset) {
-    CodeComment* a = this;
-    while (a != NULL && a->_offset != offset) {
-      a = a->_next;
-    }
-    return a;
+ public:
+  CodeString(const char * string, intptr_t offset = -1)
+    : _next(NULL), _offset(offset) {
+    _string = os::strdup(string, mtCode);
   }
 
-  // Convenience for add_comment.
-  CodeComment* find_last(intptr_t offset) {
-    CodeComment* a = find(offset);
-    if (a != NULL) {
-      while ((a->_next != NULL) && (a->_next->_offset == offset)) {
-        a = a->_next;
-      }
+  const char * string() const { return _string; }
+  intptr_t     offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset;  }
+  CodeString* next()    const { return _next; }
+
+  void set_next(CodeString* next) { _next = next; }
+
+  CodeString* first_comment() {
+    if (is_comment()) {
+      return this;
+    } else {
+      return next_comment();
     }
-    return a;
+  }
+  CodeString* next_comment() const {
+    CodeString* s = _next;
+    while (s != NULL && !s->is_comment()) {
+      s = s->_next;
+    }
+    return s;
   }
 };
 
+CodeString* CodeStrings::find(intptr_t offset) const {
+  CodeString* a = _strings->first_comment();
+  while (a != NULL && a->offset() != offset) {
+    a = a->next_comment();
+  }
+  return a;
+}
 
-void CodeComments::add_comment(intptr_t offset, const char * comment) {
-  CodeComment* c      = new CodeComment(offset, comment);
-  CodeComment* inspos = (_comments == NULL) ? NULL : _comments->find_last(offset);
+// Convenience for add_comment.
+CodeString* CodeStrings::find_last(intptr_t offset) const {
+  CodeString* a = find(offset);
+  if (a != NULL) {
+    CodeString* c = NULL;
+    while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) {
+      a = c;
+    }
+  }
+  return a;
+}
+
+void CodeStrings::add_comment(intptr_t offset, const char * comment) {
+  CodeString* c      = new CodeString(comment, offset);
+  CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
 
   if (inspos) {
     // insert after already existing comments with same offset
@@ -1062,43 +1082,47 @@
     inspos->set_next(c);
   } else {
     // no comments with such offset, yet. Insert before anything else.
-    c->set_next(_comments);
-    _comments = c;
+    c->set_next(_strings);
+    _strings = c;
   }
 }
 
-
-void CodeComments::assign(CodeComments& other) {
-  _comments = other._comments;
+void CodeStrings::assign(CodeStrings& other) {
+  _strings = other._strings;
 }
 
-
-void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) const {
-  if (_comments != NULL) {
-    CodeComment* c = _comments->find(offset);
+void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
+  if (_strings != NULL) {
+    CodeString* c = find(offset);
     while (c && c->offset() == offset) {
       stream->bol();
       stream->print("  ;; ");
-      stream->print_cr(c->comment());
-      c = c->next();
+      stream->print_cr(c->string());
+      c = c->next_comment();
     }
   }
 }
 
 
-void CodeComments::free() {
-  CodeComment* n = _comments;
+void CodeStrings::free() {
+  CodeString* n = _strings;
   while (n) {
     // unlink the node from the list saving a pointer to the next
-    CodeComment* p = n->_next;
-    n->_next = NULL;
+    CodeString* p = n->next();
+    n->set_next(NULL);
     delete n;
     n = p;
   }
-  _comments = NULL;
+  _strings = NULL;
 }
 
-
+const char* CodeStrings::add_string(const char * string) {
+  CodeString* s = new CodeString(string);
+  s->set_next(_strings);
+  _strings = s;
+  assert(s->string() != NULL, "should have a string");
+  return s->string();
+}
 
 void CodeBuffer::decode() {
   ttyLocker ttyl;
--- a/src/share/vm/asm/codeBuffer.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/asm/codeBuffer.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -28,7 +28,7 @@
 #include "code/oopRecorder.hpp"
 #include "code/relocInfo.hpp"
 
-class CodeComments;
+class CodeStrings;
 class PhaseCFG;
 class Compile;
 class BufferBlob;
@@ -240,27 +240,31 @@
 #endif //PRODUCT
 };
 
-class CodeComment;
-class CodeComments VALUE_OBJ_CLASS_SPEC {
+class CodeString;
+class CodeStrings VALUE_OBJ_CLASS_SPEC {
 private:
 #ifndef PRODUCT
-  CodeComment* _comments;
+  CodeString* _strings;
 #endif
 
+  CodeString* find(intptr_t offset) const;
+  CodeString* find_last(intptr_t offset) const;
+
 public:
-  CodeComments() {
+  CodeStrings() {
 #ifndef PRODUCT
-    _comments = NULL;
+    _strings = NULL;
 #endif
   }
 
+  const char* add_string(const char * string) PRODUCT_RETURN_(return NULL;);
+
   void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
   void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
-  void assign(CodeComments& other)  PRODUCT_RETURN;
+  void assign(CodeStrings& other)  PRODUCT_RETURN;
   void free() PRODUCT_RETURN;
 };
 
-
 // A CodeBuffer describes a memory space into which assembly
 // code is generated.  This memory space usually occupies the
 // interior of a single BufferBlob, but in some cases it may be
@@ -326,7 +330,7 @@
   csize_t      _total_size;     // size in bytes of combined memory buffer
 
   OopRecorder* _oop_recorder;
-  CodeComments _comments;
+  CodeStrings  _strings;
   OopRecorder  _default_oop_recorder;  // override with initialize_oop_recorder
   Arena*       _overflow_arena;
 
@@ -527,7 +531,7 @@
   void initialize_oop_recorder(OopRecorder* r);
 
   OopRecorder* oop_recorder() const   { return _oop_recorder; }
-  CodeComments& comments()            { return _comments; }
+  CodeStrings& strings()              { return _strings; }
 
   // Code generation
   void relocate(address at, RelocationHolder const& rspec, int format = 0) {
@@ -556,6 +560,7 @@
   address transform_address(const CodeBuffer &cb, address addr) const;
 
   void block_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
+  const char* code_string(const char* str) PRODUCT_RETURN_(return NULL;);
 
   // Log a little info about section usage in the CodeBuffer
   void log_section_sizes(const char* name);
--- a/src/share/vm/c1/c1_Canonicalizer.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Canonicalizer.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -937,4 +937,6 @@
 void Canonicalizer::do_ProfileCall(ProfileCall* x) {}
 void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {}
 void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {}
+void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
+void Canonicalizer::do_Assert(Assert* x) {}
 void Canonicalizer::do_MemBar(MemBar* x) {}
--- a/src/share/vm/c1/c1_Canonicalizer.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Canonicalizer.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -107,6 +107,8 @@
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
   virtual void do_MemBar         (MemBar*          x);
+  virtual void do_RangeCheckPredicate(RangeCheckPredicate* x);
+  virtual void do_Assert         (Assert*          x);
 };
 
 #endif // SHARE_VM_C1_C1_CANONICALIZER_HPP
--- a/src/share/vm/c1/c1_CodeStubs.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_CodeStubs.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -166,6 +166,22 @@
 #endif // PRODUCT
 };
 
+// stub used when predicate fails and deoptimization is needed
+class PredicateFailedStub: public CodeStub {
+ private:
+  CodeEmitInfo* _info;
+
+ public:
+  PredicateFailedStub(CodeEmitInfo* info);
+  virtual void emit_code(LIR_Assembler* e);
+  virtual CodeEmitInfo* info() const             { return _info; }
+  virtual void visit(LIR_OpVisitState* visitor) {
+    visitor->do_slow_case(_info);
+  }
+#ifndef PRODUCT
+  virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }
+#endif // PRODUCT
+};
 
 class DivByZeroStub: public CodeStub {
  private:
--- a/src/share/vm/c1/c1_Compilation.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Compilation.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -33,13 +33,16 @@
 #include "c1/c1_ValueStack.hpp"
 #include "code/debugInfoRec.hpp"
 #include "compiler/compileLog.hpp"
+#include "c1/c1_RangeCheckElimination.hpp"
 
 
 typedef enum {
   _t_compile,
   _t_setup,
-  _t_optimizeIR,
   _t_buildIR,
+  _t_optimize_blocks,
+  _t_optimize_null_checks,
+  _t_rangeCheckElimination,
   _t_emit_lir,
   _t_linearScan,
   _t_lirGeneration,
@@ -52,8 +55,10 @@
 static const char * timer_name[] = {
   "compile",
   "setup",
-  "optimizeIR",
   "buildIR",
+  "optimize_blocks",
+  "optimize_null_checks",
+  "rangeCheckElimination",
   "emit_lir",
   "linearScan",
   "lirGeneration",
@@ -159,9 +164,9 @@
   if (UseC1Optimizations) {
     NEEDS_CLEANUP
     // optimization
-    PhaseTraceTime timeit(_t_optimizeIR);
+    PhaseTraceTime timeit(_t_optimize_blocks);
 
-    _hir->optimize();
+    _hir->optimize_blocks();
   }
 
   _hir->verify();
@@ -180,13 +185,47 @@
   _hir->compute_code();
 
   if (UseGlobalValueNumbering) {
-    ResourceMark rm;
+    // No resource mark here! LoopInvariantCodeMotion can allocate ValueStack objects.
     int instructions = Instruction::number_of_instructions();
     GlobalValueNumbering gvn(_hir);
     assert(instructions == Instruction::number_of_instructions(),
            "shouldn't have created an instructions");
   }
 
+  _hir->verify();
+
+#ifndef PRODUCT
+  if (PrintCFGToFile) {
+    CFGPrinter::print_cfg(_hir, "Before RangeCheckElimination", true, false);
+  }
+#endif
+
+  if (RangeCheckElimination) {
+    if (_hir->osr_entry() == NULL) {
+      PhaseTraceTime timeit(_t_rangeCheckElimination);
+      RangeCheckElimination::eliminate(_hir);
+    }
+  }
+
+#ifndef PRODUCT
+  if (PrintCFGToFile) {
+    CFGPrinter::print_cfg(_hir, "After RangeCheckElimination", true, false);
+  }
+#endif
+
+  if (UseC1Optimizations) {
+    // loop invariant code motion reorders instructions and range
+    // check elimination adds new instructions so do null check
+    // elimination after.
+    NEEDS_CLEANUP
+    // optimization
+    PhaseTraceTime timeit(_t_optimize_null_checks);
+
+    _hir->eliminate_null_checks();
+  }
+
+  _hir->verify();
+
   // compute use counts after global value numbering
   _hir->compute_use_counts();
 
@@ -502,6 +541,7 @@
 , _next_id(0)
 , _next_block_id(0)
 , _code(buffer_blob)
+, _has_access_indexed(false)
 , _current_instruction(NULL)
 #ifndef PRODUCT
 , _last_instruction_printed(NULL)
@@ -567,7 +607,9 @@
   tty->print_cr("    Detailed C1 Timings");
   tty->print_cr("       Setup time:        %6.3f s (%4.1f%%)",    timers[_t_setup].seconds(),           (timers[_t_setup].seconds() / total) * 100.0);
   tty->print_cr("       Build IR:          %6.3f s (%4.1f%%)",    timers[_t_buildIR].seconds(),         (timers[_t_buildIR].seconds() / total) * 100.0);
-  tty->print_cr("         Optimize:           %6.3f s (%4.1f%%)", timers[_t_optimizeIR].seconds(),      (timers[_t_optimizeIR].seconds() / total) * 100.0);
+  float t_optimizeIR = timers[_t_optimize_blocks].seconds() + timers[_t_optimize_null_checks].seconds();
+  tty->print_cr("         Optimize:           %6.3f s (%4.1f%%)", t_optimizeIR,                         (t_optimizeIR / total) * 100.0);
+  tty->print_cr("         RCE:                %6.3f s (%4.1f%%)", timers[_t_rangeCheckElimination].seconds(),      (timers[_t_rangeCheckElimination].seconds() / total) * 100.0);
   tty->print_cr("       Emit LIR:          %6.3f s (%4.1f%%)",    timers[_t_emit_lir].seconds(),        (timers[_t_emit_lir].seconds() / total) * 100.0);
   tty->print_cr("         LIR Gen:          %6.3f s (%4.1f%%)",   timers[_t_lirGeneration].seconds(), (timers[_t_lirGeneration].seconds() / total) * 100.0);
   tty->print_cr("         Linear Scan:      %6.3f s (%4.1f%%)",   timers[_t_linearScan].seconds(),    (timers[_t_linearScan].seconds() / total) * 100.0);
--- a/src/share/vm/c1/c1_Compilation.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Compilation.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -26,8 +26,10 @@
 #define SHARE_VM_C1_C1_COMPILATION_HPP
 
 #include "ci/ciEnv.hpp"
+#include "ci/ciMethodData.hpp"
 #include "code/exceptionHandlerTable.hpp"
 #include "memory/resourceArea.hpp"
+#include "runtime/deoptimization.hpp"
 
 class CompilationResourceObj;
 class XHandlers;
@@ -85,6 +87,7 @@
   LinearScan*        _allocator;
   CodeOffsets        _offsets;
   CodeBuffer         _code;
+  bool               _has_access_indexed;
 
   // compilation helpers
   void initialize();
@@ -140,6 +143,7 @@
   C1_MacroAssembler* masm() const                { return _masm; }
   CodeOffsets* offsets()                         { return &_offsets; }
   Arena* arena()                                 { return _arena; }
+  bool has_access_indexed()                      { return _has_access_indexed; }
 
   // Instruction ids
   int get_next_id()                              { return _next_id++; }
@@ -154,6 +158,7 @@
   void set_has_fpu_code(bool f)                  { _has_fpu_code = f; }
   void set_has_unsafe_access(bool f)             { _has_unsafe_access = f; }
   void set_would_profile(bool f)                 { _would_profile = f; }
+  void set_has_access_indexed(bool f)            { _has_access_indexed = f; }
   // Add a set of exception handlers covering the given PC offset
   void add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers);
   // Statistics gathering
@@ -233,6 +238,14 @@
     return env()->comp_level() == CompLevel_full_profile &&
       C1UpdateMethodData && C1ProfileCheckcasts;
   }
+
+  // will compilation make optimistic assumptions that might lead to
+  // deoptimization and that the runtime will account for?
+  bool is_optimistic() const                             {
+    return !TieredCompilation &&
+      (RangeCheckElimination || UseLoopInvariantCodeMotion) &&
+      method()->method_data()->trap_count(Deoptimization::Reason_none) == 0;
+  }
 };
 
 
--- a/src/share/vm/c1/c1_FrameMap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_FrameMap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -308,27 +308,6 @@
   return sp_offset_for_monitor_base(index) + in_ByteSize(BasicObjectLock::obj_offset_in_bytes());
 }
 
-void FrameMap::print_frame_layout() const {
-  int svar;
-  tty->print_cr("#####################################");
-  tty->print_cr("Frame size in words %d", framesize());
-
-  if( _num_monitors > 0) {
-    tty->print_cr("monitor [0]:%d | [%2d]:%d",
-                  in_bytes(sp_offset_for_monitor_base(0)),
-                  in_bytes(sp_offset_for_monitor_base(_num_monitors)));
-  }
-  if( _num_spills > 0) {
-    svar = _num_spills - 1;
-    if(svar == 0)
-      tty->print_cr("spill   [0]:%d", in_bytes(sp_offset_for_spill(0)));
-    else
-      tty->print_cr("spill   [0]:%d | [%2d]:%d", in_bytes(sp_offset_for_spill(0)),
-                    svar,
-                    in_bytes(sp_offset_for_spill(svar)));
-  }
-}
-
 
 // For OopMaps, map a local variable or spill index to an VMReg.
 // This is the offset from sp() in the frame of the slot for the index,
--- a/src/share/vm/c1/c1_FrameMap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_FrameMap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -226,8 +226,6 @@
     return make_new_address(sp_offset_for_monitor_object(monitor_index));
   }
 
-  void print_frame_layout() const;
-
   // Creates Location describing desired slot and returns it via pointer
   // to Location object. Returns true if the stack frame offset was legal
   // (as defined by Location::legal_offset_in_bytes()), false otherwise.
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -947,7 +947,9 @@
 
 
 void GraphBuilder::load_indexed(BasicType type) {
-  ValueStack* state_before = copy_state_for_exception();
+  // In case of in block code motion in range check elimination
+  ValueStack* state_before = copy_state_indexed_access();
+  compilation()->set_has_access_indexed(true);
   Value index = ipop();
   Value array = apop();
   Value length = NULL;
@@ -961,7 +963,9 @@
 
 
 void GraphBuilder::store_indexed(BasicType type) {
-  ValueStack* state_before = copy_state_for_exception();
+  // In case of in block code motion in range check elimination
+  ValueStack* state_before = copy_state_indexed_access();
+  compilation()->set_has_access_indexed(true);
   Value value = pop(as_ValueType(type));
   Value index = ipop();
   Value array = apop();
@@ -1179,7 +1183,9 @@
   BlockBegin* tsux = block_at(stream()->get_dest());
   BlockBegin* fsux = block_at(stream()->next_bci());
   bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
-  Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb));
+  // In case of loop invariant code motion or predicate insertion
+  // before the body of a loop the state is needed
+  Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : NULL, is_bb));
 
   assert(i->as_Goto() == NULL ||
          (i->as_Goto()->sux_at(0) == tsux  && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) ||
@@ -1294,7 +1300,9 @@
     BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
     BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
-    ValueStack* state_before = is_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = copy_state_if_bb(is_bb);
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
   } else {
     // collect successors
@@ -1308,7 +1316,9 @@
     // add default successor
     if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
-    ValueStack* state_before = has_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = copy_state_if_bb(has_bb);
     Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
 #ifdef ASSERT
     if (res->as_Goto()) {
@@ -1336,7 +1346,9 @@
     BlockBegin* tsux = block_at(bci() + pair.offset());
     BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
-    ValueStack* state_before = is_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = copy_state_if_bb(is_bb);;
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
   } else {
     // collect successors & keys
@@ -1353,7 +1365,9 @@
     // add default successor
     if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
-    ValueStack* state_before = has_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = copy_state_if_bb(has_bb);
     Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
 #ifdef ASSERT
     if (res->as_Goto()) {
--- a/src/share/vm/c1/c1_GraphBuilder.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_GraphBuilder.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -301,6 +301,8 @@
   ValueStack* copy_state_exhandling();
   ValueStack* copy_state_for_exception_with_bci(int bci);
   ValueStack* copy_state_for_exception();
+  ValueStack* copy_state_if_bb(bool is_bb) { return (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL; }
+  ValueStack* copy_state_indexed_access() { return compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception(); }
 
   //
   // Inlining support
--- a/src/share/vm/c1/c1_IR.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_IR.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -182,13 +182,14 @@
 // Implementation of CodeEmitInfo
 
 // Stack must be NON-null
-CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers)
+CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, bool deoptimize_on_exception)
   : _scope(stack->scope())
   , _scope_debug_info(NULL)
   , _oop_map(NULL)
   , _stack(stack)
   , _exception_handlers(exception_handlers)
-  , _is_method_handle_invoke(false) {
+  , _is_method_handle_invoke(false)
+  , _deoptimize_on_exception(deoptimize_on_exception) {
   assert(_stack != NULL, "must be non null");
 }
 
@@ -199,7 +200,8 @@
   , _scope_debug_info(NULL)
   , _oop_map(NULL)
   , _stack(stack == NULL ? info->_stack : stack)
-  , _is_method_handle_invoke(info->_is_method_handle_invoke) {
+  , _is_method_handle_invoke(info->_is_method_handle_invoke)
+  , _deoptimize_on_exception(info->_deoptimize_on_exception) {
 
   // deep copy of exception handlers
   if (info->_exception_handlers != NULL) {
@@ -239,7 +241,7 @@
 }
 
 
-void IR::optimize() {
+void IR::optimize_blocks() {
   Optimizer opt(this);
   if (!compilation()->profile_branches()) {
     if (DoCEE) {
@@ -257,6 +259,10 @@
 #endif
     }
   }
+}
+
+void IR::eliminate_null_checks() {
+  Optimizer opt(this);
   if (EliminateNullChecks) {
     opt.eliminate_null_checks();
 #ifndef PRODUCT
@@ -429,6 +435,7 @@
   BlockList  _loop_end_blocks;     // list of all loop end blocks collected during count_edges
   BitMap2D   _loop_map;            // two-dimensional bit set: a bit is set if a block is contained in a loop
   BlockList  _work_list;           // temporary list (used in mark_loops and compute_order)
+  BlockList  _loop_headers;
 
   Compilation* _compilation;
 
@@ -594,6 +601,7 @@
     TRACE_LINEAR_SCAN(3, tty->print_cr("Block B%d is loop header of loop %d", cur->block_id(), _num_loops));
 
     cur->set_loop_index(_num_loops);
+    _loop_headers.append(cur);
     _num_loops++;
   }
 
@@ -656,6 +664,16 @@
       // -> this is not a natural loop, so ignore it
       TRACE_LINEAR_SCAN(2, tty->print_cr("Loop %d is non-natural, so it is ignored", i));
 
+      BlockBegin *loop_header = _loop_headers.at(i);
+      assert(loop_header->is_set(BlockBegin::linear_scan_loop_header_flag), "Must be loop header");
+
+      for (int j = 0; j < loop_header->number_of_preds(); j++) {
+        BlockBegin *pred = loop_header->pred_at(j);
+        pred->clear(BlockBegin::linear_scan_loop_end_flag);
+      }
+
+      loop_header->clear(BlockBegin::linear_scan_loop_header_flag);
+
       for (int block_id = _max_block_id - 1; block_id >= 0; block_id--) {
         clear_block_in_loop(i, block_id);
       }
@@ -729,9 +747,20 @@
 
   } else if (!(cur->is_set(BlockBegin::linear_scan_loop_header_flag) && parent->is_set(BlockBegin::linear_scan_loop_end_flag))) {
     TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: computing dominator of B%d: common dominator of B%d and B%d is B%d", cur->block_id(), parent->block_id(), cur->dominator()->block_id(), common_dominator(cur->dominator(), parent)->block_id()));
-    assert(cur->number_of_preds() > 1, "");
+    // Does not hold for exception blocks
+    assert(cur->number_of_preds() > 1 || cur->is_set(BlockBegin::exception_entry_flag), "");
     cur->set_dominator(common_dominator(cur->dominator(), parent));
   }
+
+  // Additional edge to xhandler of all our successors
+  // range check elimination needs that the state at the end of a
+  // block be valid in every block it dominates so cur must dominate
+  // the exception handlers of its successors.
+  int num_cur_xhandler = cur->number_of_exception_handlers();
+  for (int j = 0; j < num_cur_xhandler; j++) {
+    BlockBegin* xhandler = cur->exception_handler_at(j);
+    compute_dominator(xhandler, parent);
+  }
 }
 
 
@@ -898,7 +927,6 @@
     num_sux = cur->number_of_exception_handlers();
     for (i = 0; i < num_sux; i++) {
       BlockBegin* sux = cur->exception_handler_at(i);
-      compute_dominator(sux, cur);
       if (ready_for_processing(sux)) {
         sort_into_work_list(sux);
       }
@@ -918,8 +946,23 @@
 
     BlockBegin* dominator = block->pred_at(0);
     int num_preds = block->number_of_preds();
-    for (int i = 1; i < num_preds; i++) {
-      dominator = common_dominator(dominator, block->pred_at(i));
+
+    TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: Processing B%d", block->block_id()));
+
+    for (int j = 0; j < num_preds; j++) {
+
+      BlockBegin *pred = block->pred_at(j);
+      TRACE_LINEAR_SCAN(4, tty->print_cr("   DOM: Subrocessing B%d", pred->block_id()));
+
+      if (block->is_set(BlockBegin::exception_entry_flag)) {
+        dominator = common_dominator(dominator, pred);
+        int num_pred_preds = pred->number_of_preds();
+        for (int k = 0; k < num_pred_preds; k++) {
+          dominator = common_dominator(dominator, pred->pred_at(k));
+        }
+      } else {
+        dominator = common_dominator(dominator, pred);
+      }
     }
 
     if (dominator != block->dominator()) {
@@ -946,6 +989,21 @@
 
   // check that dominators are correct
   assert(!compute_dominators_iter(), "fix point not reached");
+
+  // Add Blocks to dominates-Array
+  int num_blocks = _linear_scan_order->length();
+  for (int i = 0; i < num_blocks; i++) {
+    BlockBegin* block = _linear_scan_order->at(i);
+
+    BlockBegin *dom = block->dominator();
+    if (dom) {
+      assert(dom->dominator_depth() != -1, "Dominator must have been visited before");
+      dom->dominates()->append(block);
+      block->set_dominator_depth(dom->dominator_depth() + 1);
+    } else {
+      block->set_dominator_depth(0);
+    }
+  }
 }
 
 
@@ -1032,7 +1090,7 @@
       BlockBegin* sux = cur->sux_at(j);
 
       assert(sux->linear_scan_number() >= 0 && sux->linear_scan_number() == _linear_scan_order->index_of(sux), "incorrect linear_scan_number");
-      if (!cur->is_set(BlockBegin::linear_scan_loop_end_flag)) {
+      if (!sux->is_set(BlockBegin::backward_branch_target_flag)) {
         assert(cur->linear_scan_number() < sux->linear_scan_number(), "invalid order");
       }
       if (cur->loop_depth() == sux->loop_depth()) {
@@ -1044,7 +1102,7 @@
       BlockBegin* pred = cur->pred_at(j);
 
       assert(pred->linear_scan_number() >= 0 && pred->linear_scan_number() == _linear_scan_order->index_of(pred), "incorrect linear_scan_number");
-      if (!cur->is_set(BlockBegin::linear_scan_loop_header_flag)) {
+      if (!cur->is_set(BlockBegin::backward_branch_target_flag)) {
         assert(cur->linear_scan_number() > pred->linear_scan_number(), "invalid order");
       }
       if (cur->loop_depth() == pred->loop_depth()) {
@@ -1060,7 +1118,8 @@
     } else {
       assert(cur->dominator() != NULL, "all but first block must have dominator");
     }
-    assert(cur->number_of_preds() != 1 || cur->dominator() == cur->pred_at(0), "Single predecessor must also be dominator");
+    // Assertion does not hold for exception handlers
+    assert(cur->number_of_preds() != 1 || cur->dominator() == cur->pred_at(0) || cur->is_set(BlockBegin::exception_entry_flag), "Single predecessor must also be dominator");
   }
 
   // check that all loops are continuous
@@ -1249,9 +1308,22 @@
   }
 };
 
+class VerifyBlockBeginField : public BlockClosure {
+
+public:
+
+  virtual void block_do(BlockBegin *block) {
+    for ( Instruction *cur = block; cur != NULL; cur = cur->next()) {
+      assert(cur->block() == block, "Block begin is not correct");
+    }
+  }
+};
+
 void IR::verify() {
 #ifdef ASSERT
   PredecessorValidator pv(this);
+  VerifyBlockBeginField verifier;
+  this->iterate_postorder(&verifier);
 #endif
 }
 
--- a/src/share/vm/c1/c1_IR.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_IR.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -255,6 +255,7 @@
   OopMap*           _oop_map;
   ValueStack*       _stack;                      // used by deoptimization (contains also monitors
   bool              _is_method_handle_invoke;    // true if the associated call site is a MethodHandle call site.
+  bool              _deoptimize_on_exception;
 
   FrameMap*     frame_map() const                { return scope()->compilation()->frame_map(); }
   Compilation*  compilation() const              { return scope()->compilation(); }
@@ -262,7 +263,7 @@
  public:
 
   // use scope from ValueStack
-  CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers);
+  CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, bool deoptimize_on_exception = false);
 
   // make a copy
   CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack = NULL);
@@ -273,6 +274,7 @@
   IRScope* scope() const                         { return _scope; }
   XHandlers* exception_handlers() const          { return _exception_handlers; }
   ValueStack* stack() const                      { return _stack; }
+  bool deoptimize_on_exception() const           { return _deoptimize_on_exception; }
 
   void add_register_oop(LIR_Opr opr);
   void record_debug_info(DebugInformationRecorder* recorder, int pc_offset);
@@ -310,7 +312,8 @@
   int              max_stack() const             { return top_scope()->max_stack(); } // expensive
 
   // ir manipulation
-  void optimize();
+  void optimize_blocks();
+  void eliminate_null_checks();
   void compute_predecessors();
   void split_critical_edges();
   void compute_code();
--- a/src/share/vm/c1/c1_Instruction.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Instruction.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -34,6 +34,15 @@
 // Implementation of Instruction
 
 
+int Instruction::dominator_depth() {
+  int result = -1;
+  if (block()) {
+    result = block()->dominator_depth();
+  }
+  assert(result != -1 || this->as_Local(), "Only locals have dominator depth -1");
+  return result;
+}
+
 Instruction::Condition Instruction::mirror(Condition cond) {
   switch (cond) {
     case eql: return eql;
@@ -42,6 +51,8 @@
     case leq: return geq;
     case gtr: return lss;
     case geq: return leq;
+    case aeq: return beq;
+    case beq: return aeq;
   }
   ShouldNotReachHere();
   return eql;
@@ -56,6 +67,8 @@
     case leq: return gtr;
     case gtr: return leq;
     case geq: return lss;
+    case aeq: assert(false, "Above equal cannot be negated");
+    case beq: assert(false, "Below equal cannot be negated");
   }
   ShouldNotReachHere();
   return eql;
@@ -70,10 +83,10 @@
   }
 }
 
-
-Instruction* Instruction::prev(BlockBegin* block) {
+// Prev without need to have BlockBegin
+Instruction* Instruction::prev() {
   Instruction* p = NULL;
-  Instruction* q = block;
+  Instruction* q = block();
   while (q != this) {
     assert(q != NULL, "this is not in the block's instruction list");
     p = q; q = q->next();
@@ -122,15 +135,24 @@
 
 // perform constant and interval tests on index value
 bool AccessIndexed::compute_needs_range_check() {
-  Constant* clength = length()->as_Constant();
-  Constant* cindex = index()->as_Constant();
-  if (clength && cindex) {
-    IntConstant* l = clength->type()->as_IntConstant();
-    IntConstant* i = cindex->type()->as_IntConstant();
-    if (l && i && i->value() < l->value() && i->value() >= 0) {
-      return false;
+
+  if (length()) {
+
+    Constant* clength = length()->as_Constant();
+    Constant* cindex = index()->as_Constant();
+    if (clength && cindex) {
+      IntConstant* l = clength->type()->as_IntConstant();
+      IntConstant* i = cindex->type()->as_IntConstant();
+      if (l && i && i->value() < l->value() && i->value() >= 0) {
+        return false;
+      }
     }
   }
+
+  if (!this->check_flag(NeedsRangeCheckFlag)) {
+    return false;
+  }
+
   return true;
 }
 
@@ -631,19 +653,25 @@
 // of the inserted block, without recomputing the values of the other blocks
 // in the CFG. Therefore the value of "depth_first_number" in BlockBegin becomes meaningless.
 BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) {
-  BlockBegin* new_sux = new BlockBegin(end()->state()->bci());
+  int bci = sux->bci();
+  // critical edge splitting may introduce a goto after a if and array
+  // bound check elimination may insert a predicate between the if and
+  // goto. The bci of the goto can't be the one of the if otherwise
+  // the state and bci are inconsistent and a deoptimization triggered
+  // by the predicate would lead to incorrect execution/a crash.
+  BlockBegin* new_sux = new BlockBegin(bci);
 
   // mark this block (special treatment when block order is computed)
   new_sux->set(critical_edge_split_flag);
 
   // This goto is not a safepoint.
   Goto* e = new Goto(sux, false);
-  new_sux->set_next(e, end()->state()->bci());
+  new_sux->set_next(e, bci);
   new_sux->set_end(e);
   // setup states
   ValueStack* s = end()->state();
-  new_sux->set_state(s->copy());
-  e->set_state(s->copy());
+  new_sux->set_state(s->copy(s->kind(), bci));
+  e->set_state(s->copy(s->kind(), bci));
   assert(new_sux->state()->locals_size() == s->locals_size(), "local size mismatch!");
   assert(new_sux->state()->stack_size() == s->stack_size(), "stack size mismatch!");
   assert(new_sux->state()->locks_size() == s->locks_size(), "locks size mismatch!");
@@ -960,15 +988,14 @@
   BlockList* sux = NULL;
   if (begin != NULL) {
     sux = begin->successors();
-  } else if (_begin != NULL) {
+  } else if (this->begin() != NULL) {
     // copy our sux list
-    BlockList* sux = new BlockList(_begin->number_of_sux());
-    for (int i = 0; i < _begin->number_of_sux(); i++) {
-      sux->append(_begin->sux_at(i));
+    BlockList* sux = new BlockList(this->begin()->number_of_sux());
+    for (int i = 0; i < this->begin()->number_of_sux(); i++) {
+      sux->append(this->begin()->sux_at(i));
     }
   }
   _sux = sux;
-  _begin = begin;
 }
 
 
@@ -1008,7 +1035,38 @@
   }
 }
 
+#ifdef ASSERT
+// Constructor of Assert
+Assert::Assert(Value x, Condition cond, bool unordered_is_true, Value y) : Instruction(illegalType)
+  , _x(x)
+  , _cond(cond)
+  , _y(y)
+{
+  set_flag(UnorderedIsTrueFlag, unordered_is_true);
+  assert(x->type()->tag() == y->type()->tag(), "types must match");
+  pin();
 
+  stringStream strStream;
+  Compilation::current()->method()->print_name(&strStream);
+
+  stringStream strStream1;
+  InstructionPrinter ip1(1, &strStream1);
+  ip1.print_instr(x);
+
+  stringStream strStream2;
+  InstructionPrinter ip2(1, &strStream2);
+  ip2.print_instr(y);
+
+  stringStream ss;
+  ss.print("Assertion %s %s %s in method %s", strStream1.as_string(), ip2.cond_name(cond), strStream2.as_string(), strStream.as_string());
+
+  _message = ss.as_string();
+}
+#endif
+
+void RangeCheckPredicate::check_state() {
+  assert(state()->kind() != ValueStack::EmptyExceptionState && state()->kind() != ValueStack::ExceptionState, "will deopt with empty state");
+}
 
 void ProfileInvoke::state_values_do(ValueVisitor* f) {
   if (state() != NULL) state()->values_do(f);
--- a/src/share/vm/c1/c1_Instruction.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Instruction.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -110,6 +110,8 @@
 class   ProfileInvoke;
 class   RuntimeCall;
 class   MemBar;
+class   RangeCheckPredicate;
+class   Assert;
 
 // A Value is a reference to the instruction creating the value
 typedef Instruction* Value;
@@ -210,6 +212,10 @@
   virtual void do_ProfileInvoke  (ProfileInvoke*   x) = 0;
   virtual void do_RuntimeCall    (RuntimeCall*     x) = 0;
   virtual void do_MemBar         (MemBar*          x) = 0;
+  virtual void do_RangeCheckPredicate(RangeCheckPredicate* x) = 0;
+#ifdef ASSERT
+  virtual void do_Assert         (Assert*          x) = 0;
+#endif
 };
 
 
@@ -306,8 +312,9 @@
 
   void update_exception_state(ValueStack* state);
 
- //protected:
- public:
+ protected:
+  BlockBegin*  _block;                           // Block that contains this instruction
+
   void set_type(ValueType* type) {
     assert(type != NULL, "type must exist");
     _type = type;
@@ -342,6 +349,9 @@
     ThrowIncompatibleClassChangeErrorFlag,
     ProfileMDOFlag,
     IsLinkedInBlockFlag,
+    NeedsRangeCheckFlag,
+    InWorkListFlag,
+    DeoptimizeOnException,
     InstructionLastFlag
   };
 
@@ -351,7 +361,7 @@
 
   // 'globally' used condition values
   enum Condition {
-    eql, neq, lss, leq, gtr, geq
+    eql, neq, lss, leq, gtr, geq, aeq, beq
   };
 
   // Instructions may be pinned for many reasons and under certain conditions
@@ -381,6 +391,7 @@
   , _pin_state(0)
   , _type(type)
   , _next(NULL)
+  , _block(NULL)
   , _subst(NULL)
   , _flags(0)
   , _operand(LIR_OprFact::illegalOpr)
@@ -399,11 +410,13 @@
   int printable_bci() const                      { assert(has_printable_bci(), "_printable_bci should have been set"); return _printable_bci; }
   void set_printable_bci(int bci)                { _printable_bci = bci; }
 #endif
+  int dominator_depth();
   int use_count() const                          { return _use_count; }
   int pin_state() const                          { return _pin_state; }
   bool is_pinned() const                         { return _pin_state != 0 || PinAllInstructions; }
   ValueType* type() const                        { return _type; }
-  Instruction* prev(BlockBegin* block);          // use carefully, expensive operation
+  BlockBegin *block() const                      { return _block; }
+  Instruction* prev();                           // use carefully, expensive operation
   Instruction* next() const                      { return _next; }
   bool has_subst() const                         { return _subst != NULL; }
   Instruction* subst()                           { return _subst == NULL ? this : _subst->subst(); }
@@ -432,6 +445,9 @@
     assert(as_BlockEnd() == NULL, "BlockEnd instructions must have no next");
     assert(next->can_be_linked(), "shouldn't link these instructions into list");
 
+    BlockBegin *block = this->block();
+    next->_block = block;
+
     next->set_flag(Instruction::IsLinkedInBlockFlag, true);
     _next = next;
     return next;
@@ -444,6 +460,29 @@
     return set_next(next);
   }
 
+  // when blocks are merged
+  void fixup_block_pointers() {
+    Instruction *cur = next()->next(); // next()'s block is set in set_next
+    while (cur && cur->_block != block()) {
+      cur->_block = block();
+      cur = cur->next();
+    }
+  }
+
+  Instruction *insert_after(Instruction *i) {
+    Instruction* n = _next;
+    set_next(i);
+    i->set_next(n);
+    return _next;
+  }
+
+  Instruction *insert_after_same_bci(Instruction *i) {
+#ifndef PRODUCT
+    i->set_printable_bci(printable_bci());
+#endif
+    return insert_after(i);
+  }
+
   void set_subst(Instruction* subst)             {
     assert(subst == NULL ||
            type()->base() == subst->type()->base() ||
@@ -452,6 +491,7 @@
   }
   void set_exception_handlers(XHandlers *xhandlers) { _exception_handlers = xhandlers; }
   void set_exception_state(ValueStack* s)        { check_state(s); _exception_state = s; }
+  void set_state_before(ValueStack* s)           { check_state(s); _state_before = s; }
 
   // machine-specifics
   void set_operand(LIR_Opr operand)              { assert(operand != LIR_OprFact::illegalOpr, "operand must exist"); _operand = operand; }
@@ -509,6 +549,11 @@
   virtual ExceptionObject*  as_ExceptionObject() { return NULL; }
   virtual UnsafeOp*         as_UnsafeOp()        { return NULL; }
   virtual ProfileInvoke*    as_ProfileInvoke()   { return NULL; }
+  virtual RangeCheckPredicate* as_RangeCheckPredicate() { return NULL; }
+
+#ifdef ASSERT
+  virtual Assert*           as_Assert()          { return NULL; }
+#endif
 
   virtual void visit(InstructionVisitor* v)      = 0;
 
@@ -570,7 +615,6 @@
 
 LEAF(Phi, Instruction)
  private:
-  BlockBegin* _block;    // the block to which the phi function belongs
   int         _pf_flags; // the flags of the phi function
   int         _index;    // to value on operand stack (index < 0) or to local
  public:
@@ -578,9 +622,9 @@
   Phi(ValueType* type, BlockBegin* b, int index)
   : Instruction(type->base())
   , _pf_flags(0)
-  , _block(b)
   , _index(index)
   {
+    _block = b;
     NOT_PRODUCT(set_printable_bci(Value(b)->printable_bci()));
     if (type->is_illegal()) {
       make_illegal();
@@ -603,8 +647,6 @@
   Value operand_at(int i) const;
   int   operand_count() const;
 
-  BlockBegin* block() const       { return _block; }
-
   void   set(Flag f)              { _pf_flags |=  f; }
   void   clear(Flag f)            { _pf_flags &= ~f; }
   bool   is_set(Flag f) const     { return (_pf_flags & f) != 0; }
@@ -670,6 +712,7 @@
     pin();
   }
 
+  // generic
   virtual bool can_trap() const                  { return state_before() != NULL; }
   virtual void input_values_do(ValueVisitor* f)   { /* no values */ }
 
@@ -852,6 +895,7 @@
   , _length(length)
   , _elt_type(elt_type)
   {
+    set_flag(Instruction::NeedsRangeCheckFlag, true);
     ASSERT_VALUES
   }
 
@@ -860,6 +904,7 @@
   Value length() const                           { return _length; }
   BasicType elt_type() const                     { return _elt_type; }
 
+  void clear_length()                            { _length = NULL; }
   // perform elimination of range checks involving constants
   bool compute_needs_range_check();
 
@@ -1524,6 +1569,7 @@
   int        _bci;                               // start-bci of block
   int        _depth_first_number;                // number of this block in a depth-first ordering
   int        _linear_scan_number;                // number of this block in linear-scan ordering
+  int        _dominator_depth;
   int        _loop_depth;                        // the loop nesting level of this block
   int        _loop_index;                        // number of the innermost loop of this block
   int        _flags;                             // the flags associated with this block
@@ -1535,6 +1581,7 @@
   // SSA specific fields: (factor out later)
   BlockList   _successors;                       // the successors of this block
   BlockList   _predecessors;                     // the predecessors of this block
+  BlockList   _dominates;                        // list of blocks that are dominated by this block
   BlockBegin* _dominator;                        // the dominator of this block
   // SSA specific ends
   BlockEnd*  _end;                               // the last instruction of this block
@@ -1583,10 +1630,12 @@
   , _linear_scan_number(-1)
   , _loop_depth(0)
   , _flags(0)
+  , _dominator_depth(-1)
   , _dominator(NULL)
   , _end(NULL)
   , _predecessors(2)
   , _successors(2)
+  , _dominates(2)
   , _exception_handlers(1)
   , _exception_states(NULL)
   , _exception_handler_pco(-1)
@@ -1603,6 +1652,7 @@
   , _total_preds(0)
   , _stores_to_locals()
   {
+    _block = this;
 #ifndef PRODUCT
     set_printable_bci(bci);
 #endif
@@ -1612,8 +1662,10 @@
   int block_id() const                           { return _block_id; }
   int bci() const                                { return _bci; }
   BlockList* successors()                        { return &_successors; }
+  BlockList* dominates()                         { return &_dominates; }
   BlockBegin* dominator() const                  { return _dominator; }
   int loop_depth() const                         { return _loop_depth; }
+  int dominator_depth() const                    { return _dominator_depth; }
   int depth_first_number() const                 { return _depth_first_number; }
   int linear_scan_number() const                 { return _linear_scan_number; }
   BlockEnd* end() const                          { return _end; }
@@ -1634,6 +1686,7 @@
   // manipulation
   void set_dominator(BlockBegin* dom)            { _dominator = dom; }
   void set_loop_depth(int d)                     { _loop_depth = d; }
+  void set_dominator_depth(int d)                { _dominator_depth = d; }
   void set_depth_first_number(int dfn)           { _depth_first_number = dfn; }
   void set_linear_scan_number(int lsn)           { _linear_scan_number = lsn; }
   void set_end(BlockEnd* end);
@@ -1695,7 +1748,8 @@
     parser_loop_header_flag       = 1 << 7,  // set by parser to identify blocks where phi functions can not be created on demand
     critical_edge_split_flag      = 1 << 8, // set for all blocks that are introduced when critical edges are split
     linear_scan_loop_header_flag  = 1 << 9, // set during loop-detection for LinearScan
-    linear_scan_loop_end_flag     = 1 << 10  // set during loop-detection for LinearScan
+    linear_scan_loop_end_flag     = 1 << 10, // set during loop-detection for LinearScan
+    donot_eliminate_range_checks  = 1 << 11  // Should be try to eliminate range checks in this block
   };
 
   void set(Flag f)                               { _flags |= f; }
@@ -1728,7 +1782,6 @@
 
 BASE(BlockEnd, StateSplit)
  private:
-  BlockBegin* _begin;
   BlockList*  _sux;
 
  protected:
@@ -1746,7 +1799,6 @@
   // creation
   BlockEnd(ValueType* type, ValueStack* state_before, bool is_safepoint)
   : StateSplit(type, state_before)
-  , _begin(NULL)
   , _sux(NULL)
   {
     set_flag(IsSafepointFlag, is_safepoint);
@@ -1754,7 +1806,8 @@
 
   // accessors
   bool is_safepoint() const                      { return check_flag(IsSafepointFlag); }
-  BlockBegin* begin() const                      { return _begin; }
+  // For compatibility with old code, for new code use block()
+  BlockBegin* begin() const                      { return _block; }
 
   // manipulation
   void set_begin(BlockBegin* begin);
@@ -1811,6 +1864,74 @@
   void set_direction(Direction d)                { _direction = d; }
 };
 
+#ifdef ASSERT
+LEAF(Assert, Instruction)
+  private:
+  Value       _x;
+  Condition   _cond;
+  Value       _y;
+  char        *_message;
+
+ public:
+  // creation
+  // unordered_is_true is valid for float/double compares only
+   Assert(Value x, Condition cond, bool unordered_is_true, Value y);
+
+  // accessors
+  Value x() const                                { return _x; }
+  Condition cond() const                         { return _cond; }
+  bool unordered_is_true() const                 { return check_flag(UnorderedIsTrueFlag); }
+  Value y() const                                { return _y; }
+  const char *message() const                    { return _message; }
+
+  // generic
+  virtual void input_values_do(ValueVisitor* f)  { f->visit(&_x); f->visit(&_y); }
+};
+#endif
+
+LEAF(RangeCheckPredicate, StateSplit)
+ private:
+  Value       _x;
+  Condition   _cond;
+  Value       _y;
+
+  void check_state();
+
+ public:
+  // creation
+  // unordered_is_true is valid for float/double compares only
+   RangeCheckPredicate(Value x, Condition cond, bool unordered_is_true, Value y, ValueStack* state) : StateSplit(illegalType)
+  , _x(x)
+  , _cond(cond)
+  , _y(y)
+  {
+    ASSERT_VALUES
+    set_flag(UnorderedIsTrueFlag, unordered_is_true);
+    assert(x->type()->tag() == y->type()->tag(), "types must match");
+    this->set_state(state);
+    check_state();
+  }
+
+  // Always deoptimize
+  RangeCheckPredicate(ValueStack* state) : StateSplit(illegalType)
+  {
+    this->set_state(state);
+    _x = _y = NULL;
+    check_state();
+  }
+
+  // accessors
+  Value x() const                                { return _x; }
+  Condition cond() const                         { return _cond; }
+  bool unordered_is_true() const                 { return check_flag(UnorderedIsTrueFlag); }
+  Value y() const                                { return _y; }
+
+  void always_fail()                             { _x = _y = NULL; }
+
+  // generic
+  virtual void input_values_do(ValueVisitor* f)  { StateSplit::input_values_do(f); f->visit(&_x); f->visit(&_y); }
+  HASHING3(RangeCheckPredicate, true, x()->subst(), y()->subst(), cond())
+};
 
 LEAF(If, BlockEnd)
  private:
--- a/src/share/vm/c1/c1_InstructionPrinter.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_InstructionPrinter.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -57,6 +57,8 @@
     case If::leq: return "<=";
     case If::gtr: return ">";
     case If::geq: return ">=";
+    case If::aeq: return "|>=|";
+    case If::beq: return "|<=|";
   }
   ShouldNotReachHere();
   return NULL;
@@ -181,6 +183,11 @@
   output()->put('[');
   print_value(indexed->index());
   output()->put(']');
+  if (indexed->length() != NULL) {
+    output()->put('(');
+    print_value(indexed->length());
+    output()->put(')');
+  }
 }
 
 
@@ -373,6 +380,7 @@
 void InstructionPrinter::do_LoadField(LoadField* x) {
   print_field(x);
   output()->print(" (%c)", type2char(x->field()->type()->basic_type()));
+  output()->print(" %s", x->field()->name()->as_utf8());
 }
 
 
@@ -381,6 +389,7 @@
   output()->print(" := ");
   print_value(x->value());
   output()->print(" (%c)", type2char(x->field()->type()->basic_type()));
+  output()->print(" %s", x->field()->name()->as_utf8());
 }
 
 
@@ -393,6 +402,9 @@
 void InstructionPrinter::do_LoadIndexed(LoadIndexed* x) {
   print_indexed(x);
   output()->print(" (%c)", type2char(x->elt_type()));
+  if (x->check_flag(Instruction::NeedsRangeCheckFlag)) {
+    output()->print(" [rc]");
+  }
 }
 
 
@@ -401,6 +413,9 @@
   output()->print(" := ");
   print_value(x->value());
   output()->print(" (%c)", type2char(x->elt_type()));
+  if (x->check_flag(Instruction::NeedsRangeCheckFlag)) {
+    output()->print(" [rc]");
+  }
 }
 
 void InstructionPrinter::do_NegateOp(NegateOp* x) {
@@ -843,6 +858,25 @@
   output()->put(')');
 }
 
+void InstructionPrinter::do_RangeCheckPredicate(RangeCheckPredicate* x) {
+
+  if (x->x() != NULL && x->y() != NULL) {
+    output()->print("if ");
+    print_value(x->x());
+    output()->print(" %s ", cond_name(x->cond()));
+    print_value(x->y());
+    output()->print(" then deoptimize!");
+  } else {
+    output()->print("always deoptimize!");
+  }
+}
+
+void InstructionPrinter::do_Assert(Assert* x) {
+  output()->print("assert ");
+  print_value(x->x());
+  output()->print(" %s ", cond_name(x->cond()));
+  print_value(x->y());
+}
 
 void InstructionPrinter::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {
   print_unsafe_object_op(x, "UnsafePrefetchWrite");
--- a/src/share/vm/c1/c1_InstructionPrinter.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_InstructionPrinter.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -135,6 +135,8 @@
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
   virtual void do_MemBar         (MemBar*          x);
+  virtual void do_RangeCheckPredicate(RangeCheckPredicate* x);
+  virtual void do_Assert         (Assert*          x);
 };
 #endif // PRODUCT
 
--- a/src/share/vm/c1/c1_LIR.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LIR.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -633,6 +633,7 @@
     case lir_ushr:
     case lir_xadd:
     case lir_xchg:
+    case lir_assert:
     {
       assert(op->as_Op2() != NULL, "must be");
       LIR_Op2* op2 = (LIR_Op2*)op;
@@ -1112,6 +1113,11 @@
   }
 }
 
+#ifdef ASSERT
+void LIR_OpAssert::emit_code(LIR_Assembler* masm) {
+  masm->emit_assert(this);
+}
+#endif
 
 void LIR_OpDelay::emit_code(LIR_Assembler* masm) {
   masm->emit_delay(this);
@@ -1771,6 +1777,8 @@
      case lir_cas_int:               s = "cas_int";      break;
      // LIR_OpProfileCall
      case lir_profile_call:          s = "profile_call";  break;
+     // LIR_OpAssert
+     case lir_assert:                s = "assert";        break;
      case lir_none:                  ShouldNotReachHere();break;
     default:                         s = "illegal_op";    break;
   }
@@ -2017,6 +2025,13 @@
   out->print("[lbl:0x%x]", stub()->entry());
 }
 
+void LIR_OpAssert::print_instr(outputStream* out) const {
+  print_condition(out, condition()); out->print(" ");
+  in_opr1()->print(out);             out->print(" ");
+  in_opr2()->print(out);             out->print(", \"");
+  out->print(msg());                 out->print("\"");
+}
+
 
 void LIR_OpDelay::print_instr(outputStream* out) const {
   _op->print_on(out);
--- a/src/share/vm/c1/c1_LIR.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LIR.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -881,6 +881,7 @@
 class    LIR_OpTypeCheck;
 class    LIR_OpCompareAndSwap;
 class    LIR_OpProfileCall;
+class    LIR_OpAssert;
 
 
 // LIR operation codes
@@ -1000,6 +1001,9 @@
   , begin_opMDOProfile
     , lir_profile_call
   , end_opMDOProfile
+  , begin_opAssert
+    , lir_assert
+  , end_opAssert
 };
 
 
@@ -1135,6 +1139,7 @@
   virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; }
   virtual LIR_OpCompareAndSwap* as_OpCompareAndSwap() { return NULL; }
   virtual LIR_OpProfileCall* as_OpProfileCall() { return NULL; }
+  virtual LIR_OpAssert* as_OpAssert() { return NULL; }
 
   virtual void verify() const {}
 };
@@ -1623,7 +1628,7 @@
     , _tmp3(LIR_OprFact::illegalOpr)
     , _tmp4(LIR_OprFact::illegalOpr)
     , _tmp5(LIR_OprFact::illegalOpr) {
-    assert(code == lir_cmp, "code check");
+    assert(code == lir_cmp || code == lir_assert, "code check");
   }
 
   LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type)
@@ -1683,7 +1688,7 @@
   LIR_Opr tmp4_opr() const                       { return _tmp4; }
   LIR_Opr tmp5_opr() const                       { return _tmp5; }
   LIR_Condition condition() const  {
-    assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); return _condition;
+    assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition;
   }
   void set_condition(LIR_Condition condition) {
     assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove");  _condition = condition;
@@ -1823,6 +1828,30 @@
   CodeEmitInfo* call_info() const { return info(); }
 };
 
+#ifdef ASSERT
+// LIR_OpAssert
+class LIR_OpAssert : public LIR_Op2 {
+ friend class LIR_OpVisitState;
+
+ private:
+  const char* _msg;
+  bool        _halt;
+
+ public:
+  LIR_OpAssert(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, const char* msg, bool halt)
+    : LIR_Op2(lir_assert, condition, opr1, opr2)
+    , _halt(halt)
+    , _msg(msg) {
+  }
+
+  const char* msg() const                        { return _msg; }
+  bool        halt() const                       { return _halt; }
+
+  virtual void emit_code(LIR_Assembler* masm);
+  virtual LIR_OpAssert* as_OpAssert()            { return this; }
+  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
+};
+#endif
 
 // LIR_OpCompareAndSwap
 class LIR_OpCompareAndSwap : public LIR_Op {
@@ -2196,6 +2225,9 @@
 
   void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); }
   void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); }
+#ifdef ASSERT
+  void lir_assert(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, const char* msg, bool halt) { append(new LIR_OpAssert(condition, opr1, opr2, msg, halt)); }
+#endif
 };
 
 void print_LIR(BlockList* blocks);
@@ -2375,7 +2407,7 @@
   // collects all register operands of the instruction
   void visit(LIR_Op* op);
 
-#if ASSERT
+#ifdef ASSERT
   // check that an operation has no operands
   bool no_operands(LIR_Op* op);
 #endif
--- a/src/share/vm/c1/c1_LIRAssembler.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LIRAssembler.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -210,6 +210,9 @@
   void arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack);
   void arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info);
   void intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op* op);
+#ifdef ASSERT
+  void emit_assert(LIR_OpAssert* op);
+#endif
 
   void logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest);
 
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -403,6 +403,10 @@
 CodeEmitInfo* LIRGenerator::state_for(Instruction* x, ValueStack* state, bool ignore_xhandler) {
   assert(state != NULL, "state must be defined");
 
+#ifndef PRODUCT
+  state->verify();
+#endif
+
   ValueStack* s = state;
   for_each_state(s) {
     if (s->kind() == ValueStack::EmptyExceptionState) {
@@ -453,7 +457,7 @@
     }
   }
 
-  return new CodeEmitInfo(state, ignore_xhandler ? NULL : x->exception_handlers());
+  return new CodeEmitInfo(state, ignore_xhandler ? NULL : x->exception_handlers(), x->check_flag(Instruction::DeoptimizeOnException));
 }
 
 
@@ -707,25 +711,6 @@
   }
 }
 
-static Value maxvalue(IfOp* ifop) {
-  switch (ifop->cond()) {
-    case If::eql: return NULL;
-    case If::neq: return NULL;
-    case If::lss: // x <  y ? x : y
-    case If::leq: // x <= y ? x : y
-      if (ifop->x() == ifop->tval() &&
-          ifop->y() == ifop->fval()) return ifop->y();
-      return NULL;
-
-    case If::gtr: // x >  y ? y : x
-    case If::geq: // x >= y ? y : x
-      if (ifop->x() == ifop->tval() &&
-          ifop->y() == ifop->fval()) return ifop->y();
-      return NULL;
-
-  }
-}
-
 static ciType* phi_declared_type(Phi* phi) {
   ciType* t = phi->operand_at(0)->declared_type();
   if (t == NULL) {
@@ -1792,11 +1777,18 @@
   }
 #endif
 
+  bool stress_deopt = StressLoopInvariantCodeMotion && info && info->deoptimize_on_exception();
   if (x->needs_null_check() &&
       (needs_patching ||
-       MacroAssembler::needs_explicit_null_check(x->offset()))) {
+       MacroAssembler::needs_explicit_null_check(x->offset()) ||
+       stress_deopt)) {
+    LIR_Opr obj = object.result();
+    if (stress_deopt) {
+      obj = new_register(T_OBJECT);
+      __ move(LIR_OprFact::oopConst(NULL), obj);
+    }
     // emit an explicit null check because the offset is too large
-    __ null_check(object.result(), new CodeEmitInfo(info));
+    __ null_check(obj, new CodeEmitInfo(info));
   }
 
   LIR_Opr reg = rlock_result(x, field_type);
@@ -1873,6 +1865,11 @@
     } else {
       info = state_for(nc);
     }
+    if (StressLoopInvariantCodeMotion && info->deoptimize_on_exception()) {
+      LIR_Opr obj = new_register(T_OBJECT);
+      __ move(LIR_OprFact::oopConst(NULL), obj);
+      __ null_check(obj, new CodeEmitInfo(info));
+    }
   }
   __ load(new LIR_Address(array.result(), arrayOopDesc::length_offset_in_bytes(), T_INT), reg, info, lir_patch_none);
 }
@@ -1883,14 +1880,11 @@
   LIRItem array(x->array(), this);
   LIRItem index(x->index(), this);
   LIRItem length(this);
-  bool needs_range_check = true;
-
-  if (use_length) {
-    needs_range_check = x->compute_needs_range_check();
-    if (needs_range_check) {
-      length.set_instruction(x->length());
-      length.load_item();
-    }
+  bool needs_range_check = x->compute_needs_range_check();
+
+  if (use_length && needs_range_check) {
+    length.set_instruction(x->length());
+    length.load_item();
   }
 
   array.load_item();
@@ -1910,13 +1904,20 @@
     } else {
       null_check_info = range_check_info;
     }
+    if (StressLoopInvariantCodeMotion && null_check_info->deoptimize_on_exception()) {
+      LIR_Opr obj = new_register(T_OBJECT);
+      __ move(LIR_OprFact::oopConst(NULL), obj);
+      __ null_check(obj, new CodeEmitInfo(null_check_info));
+    }
   }
 
   // emit array address setup early so it schedules better
   LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), false);
 
   if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
+    if (StressLoopInvariantCodeMotion && range_check_info->deoptimize_on_exception()) {
+      __ branch(lir_cond_always, T_ILLEGAL, new RangeCheckStub(range_check_info, index.result()));
+    } else if (use_length) {
       // TODO: use a (modified) version of array_range_check that does not require a
       //       constant length to be loaded to a register
       __ cmp(lir_cond_belowEqual, length.result(), index.result());
@@ -2634,7 +2635,7 @@
       LIR_Opr lock = new_register(T_INT);
       __ load_stack_address_monitor(0, lock);
 
-      CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL);
+      CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, x->check_flag(Instruction::DeoptimizeOnException));
       CodeStub* slow_path = new MonitorEnterStub(obj, lock, info);
 
       // receiver is guaranteed non-NULL so don't need CodeEmitInfo
@@ -2644,7 +2645,7 @@
 
   // increment invocation counters if needed
   if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting.
-    CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL);
+    CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, false);
     increment_invocation_counter(info);
   }
 
@@ -3102,6 +3103,95 @@
   }
 }
 
+void LIRGenerator::do_Assert(Assert *x) {
+#ifdef ASSERT
+  ValueTag tag = x->x()->type()->tag();
+  If::Condition cond = x->cond();
+
+  LIRItem xitem(x->x(), this);
+  LIRItem yitem(x->y(), this);
+  LIRItem* xin = &xitem;
+  LIRItem* yin = &yitem;
+
+  assert(tag == intTag, "Only integer assertions are valid!");
+
+  xin->load_item();
+  yin->dont_load_item();
+
+  set_no_result(x);
+
+  LIR_Opr left = xin->result();
+  LIR_Opr right = yin->result();
+
+  __ lir_assert(lir_cond(x->cond()), left, right, x->message(), true);
+#endif
+}
+
+
+void LIRGenerator::do_RangeCheckPredicate(RangeCheckPredicate *x) {
+
+
+  Instruction *a = x->x();
+  Instruction *b = x->y();
+  if (!a || StressRangeCheckElimination) {
+    assert(!b || StressRangeCheckElimination, "B must also be null");
+
+    CodeEmitInfo *info = state_for(x, x->state());
+    CodeStub* stub = new PredicateFailedStub(info);
+
+    __ jump(stub);
+  } else if (a->type()->as_IntConstant() && b->type()->as_IntConstant()) {
+    int a_int = a->type()->as_IntConstant()->value();
+    int b_int = b->type()->as_IntConstant()->value();
+
+    bool ok = false;
+
+    switch(x->cond()) {
+      case Instruction::eql: ok = (a_int == b_int); break;
+      case Instruction::neq: ok = (a_int != b_int); break;
+      case Instruction::lss: ok = (a_int < b_int); break;
+      case Instruction::leq: ok = (a_int <= b_int); break;
+      case Instruction::gtr: ok = (a_int > b_int); break;
+      case Instruction::geq: ok = (a_int >= b_int); break;
+      case Instruction::aeq: ok = ((unsigned int)a_int >= (unsigned int)b_int); break;
+      case Instruction::beq: ok = ((unsigned int)a_int <= (unsigned int)b_int); break;
+      default: ShouldNotReachHere();
+    }
+
+    if (ok) {
+
+      CodeEmitInfo *info = state_for(x, x->state());
+      CodeStub* stub = new PredicateFailedStub(info);
+
+      __ jump(stub);
+    }
+  } else {
+
+    ValueTag tag = x->x()->type()->tag();
+    If::Condition cond = x->cond();
+    LIRItem xitem(x->x(), this);
+    LIRItem yitem(x->y(), this);
+    LIRItem* xin = &xitem;
+    LIRItem* yin = &yitem;
+
+    assert(tag == intTag, "Only integer deoptimizations are valid!");
+
+    xin->load_item();
+    yin->dont_load_item();
+    set_no_result(x);
+
+    LIR_Opr left = xin->result();
+    LIR_Opr right = yin->result();
+
+    CodeEmitInfo *info = state_for(x, x->state());
+    CodeStub* stub = new PredicateFailedStub(info);
+
+    __ cmp(lir_cond(cond), left, right);
+    __ branch(lir_cond(cond), right->type(), stub);
+  }
+}
+
+
 LIR_Opr LIRGenerator::call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info) {
   LIRItemList args(1);
   LIRItem value(arg1, this);
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -412,6 +412,8 @@
     case If::leq: l = lir_cond_lessEqual;    break;
     case If::geq: l = lir_cond_greaterEqual; break;
     case If::gtr: l = lir_cond_greater;      break;
+    case If::aeq: l = lir_cond_aboveEqual;   break;
+    case If::beq: l = lir_cond_belowEqual;   break;
     };
     return l;
   }
@@ -534,6 +536,8 @@
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
   virtual void do_MemBar         (MemBar*          x);
+  virtual void do_RangeCheckPredicate(RangeCheckPredicate* x);
+  virtual void do_Assert         (Assert*          x);
 };
 
 
--- a/src/share/vm/c1/c1_LinearScan.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_LinearScan.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -6231,26 +6231,29 @@
             assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
             LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
 
-            LIR_Op2* prev_cmp = NULL;
-
-            for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
-              prev_op = instructions->at(j);
-              if(prev_op->code() == lir_cmp) {
-                assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
-                prev_cmp = (LIR_Op2*)prev_op;
-                assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
+            if (prev_branch->stub() == NULL) {
+
+              LIR_Op2* prev_cmp = NULL;
+
+              for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
+                prev_op = instructions->at(j);
+                if (prev_op->code() == lir_cmp) {
+                  assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
+                  prev_cmp = (LIR_Op2*)prev_op;
+                  assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
+                }
               }
-            }
-            assert(prev_cmp != NULL, "should have found comp instruction for branch");
-            if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
-
-              TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
-
-              // eliminate a conditional branch to the immediate successor
-              prev_branch->change_block(last_branch->block());
-              prev_branch->negate_cond();
-              prev_cmp->set_condition(prev_branch->cond());
-              instructions->truncate(instructions->length() - 1);
+              assert(prev_cmp != NULL, "should have found comp instruction for branch");
+              if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
+
+                TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
+
+                // eliminate a conditional branch to the immediate successor
+                prev_branch->change_block(last_branch->block());
+                prev_branch->negate_cond();
+                prev_cmp->set_condition(prev_branch->cond());
+                instructions->truncate(instructions->length() - 1);
+              }
             }
           }
         }
--- a/src/share/vm/c1/c1_Optimizer.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Optimizer.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -178,7 +178,7 @@
   // 2) substitute conditional expression
   //    with an IfOp followed by a Goto
   // cut if_ away and get node before
-  Instruction* cur_end = if_->prev(block);
+  Instruction* cur_end = if_->prev();
 
   // append constants of true- and false-block if necessary
   // clone constants because original block must not be destroyed
@@ -202,7 +202,7 @@
   }
 
   // append Goto to successor
-  ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
+  ValueStack* state_before = if_->state_before();
   Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
 
   // prepare state for Goto
@@ -367,10 +367,11 @@
 #endif
 
         // find instruction before end & append first instruction of sux block
-        Instruction* prev = end->prev(block);
+        Instruction* prev = end->prev();
         Instruction* next = sux->next();
         assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd");
         prev->set_next(next);
+        prev->fixup_block_pointers();
         sux->disconnect_from_graph();
         block->set_end(sux->end());
         // add exception handlers of deleted block, if any
@@ -533,6 +534,8 @@
   void do_ProfileInvoke  (ProfileInvoke*   x);
   void do_RuntimeCall    (RuntimeCall*     x);
   void do_MemBar         (MemBar*          x);
+  void do_RangeCheckPredicate(RangeCheckPredicate* x);
+  void do_Assert         (Assert*          x);
 };
 
 
@@ -714,6 +717,8 @@
 void NullCheckVisitor::do_ProfileInvoke  (ProfileInvoke*   x) {}
 void NullCheckVisitor::do_RuntimeCall    (RuntimeCall*     x) {}
 void NullCheckVisitor::do_MemBar         (MemBar*          x) {}
+void NullCheckVisitor::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
+void NullCheckVisitor::do_Assert         (Assert*          x) {}
 
 
 void NullCheckEliminator::visit(Value* p) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/c1/c1_RangeCheckElimination.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,1517 @@
+/*
+ * 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 "c1/c1_ValueStack.hpp"
+#include "c1/c1_RangeCheckElimination.hpp"
+#include "c1/c1_IR.hpp"
+#include "c1/c1_Canonicalizer.hpp"
+#include "c1/c1_ValueMap.hpp"
+#include "ci/ciMethodData.hpp"
+#include "runtime/deoptimization.hpp"
+
+// Macros for the Trace and the Assertion flag
+#ifdef ASSERT
+#define TRACE_RANGE_CHECK_ELIMINATION(code) if (TraceRangeCheckElimination) { code; }
+#define ASSERT_RANGE_CHECK_ELIMINATION(code) if (AssertRangeCheckElimination) { code; }
+#define TRACE_OR_ASSERT_RANGE_CHECK_ELIMINATION(code) if (TraceRangeCheckElimination || AssertRangeCheckElimination) { code; }
+#else
+#define TRACE_RANGE_CHECK_ELIMINATION(code)
+#define ASSERT_RANGE_CHECK_ELIMINATION(code)
+#define TRACE_OR_ASSERT_RANGE_CHECK_ELIMINATION(code)
+#endif
+
+// Entry point for the optimization
+void RangeCheckElimination::eliminate(IR *ir) {
+  bool do_elimination = ir->compilation()->has_access_indexed();
+  ASSERT_RANGE_CHECK_ELIMINATION(do_elimination = true);
+  if (do_elimination) {
+    RangeCheckEliminator rce(ir);
+  }
+}
+
+// Constructor
+RangeCheckEliminator::RangeCheckEliminator(IR *ir) :
+  _bounds(Instruction::number_of_instructions(), NULL),
+  _access_indexed_info(Instruction::number_of_instructions(), NULL)
+{
+  _visitor.set_range_check_eliminator(this);
+  _ir = ir;
+  _number_of_instructions = Instruction::number_of_instructions();
+  _optimistic = ir->compilation()->is_optimistic();
+
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("");
+    tty->print_cr("Range check elimination");
+    ir->method()->print_name(tty);
+    tty->print_cr("");
+  );
+
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("optimistic=%d", (int)_optimistic);
+  );
+
+#ifdef ASSERT
+  // Verifies several conditions that must be true on the IR-input. Only used for debugging purposes.
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("Verification of IR . . .");
+  );
+  Verification verification(ir);
+#endif
+
+  // Set process block flags
+  // Optimization so a blocks is only processed if it contains an access indexed instruction or if
+  // one of its children in the dominator tree contains an access indexed instruction.
+  set_process_block_flags(ir->start());
+
+  // Pass over instructions in the dominator tree
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("Starting pass over dominator tree . . .")
+  );
+  calc_bounds(ir->start(), NULL);
+
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("Finished!")
+  );
+}
+
+// Instruction specific work for some instructions
+// Constant
+void RangeCheckEliminator::Visitor::do_Constant(Constant *c) {
+  IntConstant *ic = c->type()->as_IntConstant();
+  if (ic != NULL) {
+    int value = ic->value();
+    _bound = new Bound(value, NULL, value, NULL);
+  }
+}
+
+// LogicOp
+void RangeCheckEliminator::Visitor::do_LogicOp(LogicOp *lo) {
+  if (lo->type()->as_IntType() && lo->op() == Bytecodes::_iand && (lo->x()->as_Constant() || lo->y()->as_Constant())) {
+    int constant = 0;
+    Constant *c = lo->x()->as_Constant();
+    if (c != NULL) {
+      constant = c->type()->as_IntConstant()->value();
+    } else {
+      constant = lo->y()->as_Constant()->type()->as_IntConstant()->value();
+    }
+    if (constant >= 0) {
+      _bound = new Bound(0, NULL, constant, NULL);
+    }
+  }
+}
+
+// Phi
+void RangeCheckEliminator::Visitor::do_Phi(Phi *phi) {
+  if (!phi->type()->as_IntType() && !phi->type()->as_ObjectType()) return;
+
+  BlockBegin *block = phi->block();
+  int op_count = phi->operand_count();
+  bool has_upper = true;
+  bool has_lower = true;
+  assert(phi, "Phi must not be null");
+  Bound *bound = NULL;
+
+  // TODO: support more difficult phis
+  for (int i=0; i<op_count; i++) {
+    Value v = phi->operand_at(i);
+
+    if (v == phi) continue;
+
+    // Check if instruction is connected with phi itself
+    Op2 *op2 = v->as_Op2();
+    if (op2 != NULL) {
+      Value x = op2->x();
+      Value y = op2->y();
+      if ((x == phi || y == phi)) {
+        Value other = x;
+        if (other == phi) {
+          other = y;
+        }
+        ArithmeticOp *ao = v->as_ArithmeticOp();
+        if (ao != NULL && ao->op() == Bytecodes::_iadd) {
+          assert(ao->op() == Bytecodes::_iadd, "Has to be add!");
+          if (ao->type()->as_IntType()) {
+            Constant *c = other->as_Constant();
+            if (c != NULL) {
+              assert(c->type()->as_IntConstant(), "Constant has to be of type integer");
+              int value = c->type()->as_IntConstant()->value();
+              if (value == 1) {
+                has_upper = false;
+              } else if (value > 1) {
+                // Overflow not guaranteed
+                has_upper = false;
+                has_lower = false;
+              } else if (value < 0) {
+                has_lower = false;
+              }
+              continue;
+            }
+          }
+        }
+      }
+    }
+
+    // No connection -> new bound
+    Bound *v_bound = _rce->get_bound(v);
+    Bound *cur_bound;
+    int cur_constant = 0;
+    Value cur_value = v;
+
+    if (v->type()->as_IntConstant()) {
+      cur_constant = v->type()->as_IntConstant()->value();
+      cur_value = NULL;
+    }
+    if (!v_bound->has_upper() || !v_bound->has_lower()) {
+      cur_bound = new Bound(cur_constant, cur_value, cur_constant, cur_value);
+    } else {
+      cur_bound = v_bound;
+    }
+    if (cur_bound) {
+      if (!bound) {
+        bound = cur_bound->copy();
+      } else {
+        bound->or_op(cur_bound);
+      }
+    } else {
+      // No bound!
+      bound = NULL;
+      break;
+    }
+  }
+
+  if (bound) {
+    if (!has_upper) {
+      bound->remove_upper();
+    }
+    if (!has_lower) {
+      bound->remove_lower();
+    }
+    _bound = bound;
+  } else {
+    _bound = new Bound();
+  }
+}
+
+
+// ArithmeticOp
+void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) {
+  Value x = ao->x();
+  Value y = ao->y();
+
+  if (ao->op() == Bytecodes::_irem) {
+    Bound* x_bound = _rce->get_bound(x);
+    Bound* y_bound = _rce->get_bound(y);
+    if (x_bound->lower() >= 0 && x_bound->lower_instr() == NULL && y->as_ArrayLength() != NULL) {
+      _bound = new Bound(0, NULL, -1, y);
+    } else {
+      _bound = new Bound();
+    }
+  } else if (!x->as_Constant() || !y->as_Constant()) {
+    assert(!x->as_Constant() || !y->as_Constant(), "One of the operands must be non-constant!");
+    if (((x->as_Constant() || y->as_Constant()) && (ao->op() == Bytecodes::_iadd)) || (y->as_Constant() && ao->op() == Bytecodes::_isub)) {
+      assert(ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub, "Operand must be iadd or isub");
+
+      if (y->as_Constant()) {
+        Value tmp = x;
+        x = y;
+        y = tmp;
+      }
+      assert(x->as_Constant()->type()->as_IntConstant(), "Constant must be int constant!");
+
+      // Constant now in x
+      int const_value = x->as_Constant()->type()->as_IntConstant()->value();
+      if (ao->op() == Bytecodes::_iadd || const_value != min_jint) {
+        if (ao->op() == Bytecodes::_isub) {
+          const_value = -const_value;
+        }
+
+        Bound * bound = _rce->get_bound(y);
+        if (bound->has_upper() && bound->has_lower()) {
+          int new_lower = bound->lower() + const_value;
+          jlong new_lowerl = ((jlong)bound->lower()) + const_value;
+          int new_upper = bound->upper() + const_value;
+          jlong new_upperl = ((jlong)bound->upper()) + const_value;
+
+          if (((jlong)new_lower) == new_lowerl && ((jlong)new_upper == new_upperl)) {
+            Bound *newBound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr());
+            _bound = newBound;
+          } else {
+            // overflow
+            _bound = new Bound();
+          }
+        } else {
+          _bound = new Bound();
+        }
+      } else {
+        _bound = new Bound();
+      }
+    } else {
+      Bound *bound = _rce->get_bound(x);
+      if (ao->op() == Bytecodes::_isub) {
+        if (bound->lower_instr() == y) {
+          _bound = new Bound(Instruction::geq, NULL, bound->lower());
+        } else {
+          _bound = new Bound();
+        }
+      } else {
+        _bound = new Bound();
+      }
+    }
+  }
+}
+
+// IfOp
+void RangeCheckEliminator::Visitor::do_IfOp(IfOp *ifOp)
+{
+  if (ifOp->tval()->type()->as_IntConstant() && ifOp->fval()->type()->as_IntConstant()) {
+    int min = ifOp->tval()->type()->as_IntConstant()->value();
+    int max = ifOp->fval()->type()->as_IntConstant()->value();
+    if (min > max) {
+      // min ^= max ^= min ^= max;
+      int tmp = min;
+      min = max;
+      max = tmp;
+    }
+    _bound = new Bound(min, NULL, max, NULL);
+  }
+}
+
+// Get bound. Returns the current bound on Value v. Normally this is the topmost element on the bound stack.
+RangeCheckEliminator::Bound *RangeCheckEliminator::get_bound(Value v) {
+  // Wrong type or NULL -> No bound
+  if (!v || (!v->type()->as_IntType() && !v->type()->as_ObjectType())) return NULL;
+
+  if (!_bounds[v->id()]) {
+    // First (default) bound is calculated
+    // Create BoundStack
+    _bounds[v->id()] = new BoundStack();
+    _visitor.clear_bound();
+    Value visit_value = v;
+    visit_value->visit(&_visitor);
+    Bound *bound = _visitor.bound();
+    if (bound) {
+      _bounds[v->id()]->push(bound);
+    }
+    if (_bounds[v->id()]->length() == 0) {
+      assert(!(v->as_Constant() && v->type()->as_IntConstant()), "constants not handled here");
+      _bounds[v->id()]->push(new Bound());
+    }
+  } else if (_bounds[v->id()]->length() == 0) {
+    // To avoid endless loops, bound is currently in calculation -> nothing known about it
+    return new Bound();
+  }
+
+  // Return bound
+  return _bounds[v->id()]->top();
+}
+
+// Update bound
+void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant) {
+  if (cond == Instruction::gtr) {
+    cond = Instruction::geq;
+    constant++;
+  } else if (cond == Instruction::lss) {
+    cond = Instruction::leq;
+    constant--;
+  }
+  Bound *bound = new Bound(cond, value, constant);
+  update_bound(pushed, v, bound);
+}
+
+// Checks for loop invariance. Returns true if the instruction is outside of the loop which is identified by loop_header.
+bool RangeCheckEliminator::loop_invariant(BlockBegin *loop_header, Instruction *instruction) {
+  assert(loop_header, "Loop header must not be null!");
+  if (!instruction) return true;
+  return instruction->dominator_depth() < loop_header->dominator_depth();
+}
+
+// Update bound. Pushes a new bound onto the stack. Tries to do a conjunction with the current bound.
+void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Bound *bound) {
+  if (v->as_Constant()) {
+    // No bound update for constants
+    return;
+  }
+  if (!_bounds[v->id()]) {
+    get_bound(v);
+    assert(_bounds[v->id()], "Now Stack must exist");
+  }
+  Bound *top = NULL;
+  if (_bounds[v->id()]->length() > 0) {
+    top = _bounds[v->id()]->top();
+  }
+  if (top) {
+    bound->and_op(top);
+  }
+  _bounds[v->id()]->push(bound);
+  pushed.append(v->id());
+}
+
+// Add instruction + idx for in block motion
+void RangeCheckEliminator::add_access_indexed_info(InstructionList &indices, int idx, Value instruction, AccessIndexed *ai) {
+  int id = instruction->id();
+  AccessIndexedInfo *aii = _access_indexed_info[id];
+  if (aii == NULL) {
+    aii = new AccessIndexedInfo();
+    _access_indexed_info[id] = aii;
+    indices.append(instruction);
+    aii->_min = idx;
+    aii->_max = idx;
+    aii->_list = new AccessIndexedList();
+  } else if (idx >= aii->_min && idx <= aii->_max) {
+    remove_range_check(ai);
+    return;
+  }
+  aii->_min = MIN2(aii->_min, idx);
+  aii->_max = MAX2(aii->_max, idx);
+  aii->_list->append(ai);
+}
+
+// In block motion. Tries to reorder checks in order to reduce some of them.
+// Example:
+// a[i] = 0;
+// a[i+2] = 0;
+// a[i+1] = 0;
+// In this example the check for a[i+1] would be considered as unnecessary during the first iteration.
+// After this i is only checked once for i >= 0 and i+2 < a.length before the first array access. If this
+// check fails, deoptimization is called.
+void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays) {
+  InstructionList indices;
+
+  // Now iterate over all arrays
+  for (int i=0; i<arrays.length(); i++) {
+    int max_constant = -1;
+    AccessIndexedList list_constant;
+    Value array = arrays.at(i);
+
+    // For all AccessIndexed-instructions in this block concerning the current array.
+    for(int j=0; j<accessIndexed.length(); j++) {
+      AccessIndexed *ai = accessIndexed.at(j);
+      if (ai->array() != array || !ai->check_flag(Instruction::NeedsRangeCheckFlag)) continue;
+
+      Value index = ai->index();
+      Constant *c = index->as_Constant();
+      if (c != NULL) {
+        int constant_value = c->type()->as_IntConstant()->value();
+        if (constant_value >= 0) {
+          if (constant_value <= max_constant) {
+            // No range check needed for this
+            remove_range_check(ai);
+          } else {
+            max_constant = constant_value;
+            list_constant.append(ai);
+          }
+        }
+      } else {
+        int last_integer = 0;
+        Instruction *last_instruction = index;
+        int base = 0;
+        ArithmeticOp *ao = index->as_ArithmeticOp();
+
+        while (ao != NULL && (ao->x()->as_Constant() || ao->y()->as_Constant()) && (ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub)) {
+          c = ao->y()->as_Constant();
+          Instruction *other = ao->x();
+          if (!c && ao->op() == Bytecodes::_iadd) {
+            c = ao->x()->as_Constant();
+            other = ao->y();
+          }
+
+          if (c) {
+            int value = c->type()->as_IntConstant()->value();
+            if (value != min_jint) {
+              if (ao->op() == Bytecodes::_isub) {
+                value = -value;
+              }
+              base += value;
+              last_integer = base;
+              last_instruction = other;
+            }
+            index = other;
+          } else {
+            break;
+          }
+          ao = index->as_ArithmeticOp();
+        }
+        add_access_indexed_info(indices, last_integer, last_instruction, ai);
+      }
+    }
+
+    // Iterate over all different indices
+    if (_optimistic) {
+      for (int i=0; i<indices.length(); i++) {
+        Instruction *index_instruction = indices.at(i);
+        AccessIndexedInfo *info = _access_indexed_info[index_instruction->id()];
+        assert(info != NULL, "Info must not be null");
+
+        // if idx < 0, max > 0, max + idx may fall between 0 and
+        // length-1 and if min < 0, min + idx may overflow and be >=
+        // 0. The predicate wouldn't trigger but some accesses could
+        // be with a negative index. This test guarantees that for the
+        // min and max value that are kept the predicate can't let
+        // some incorrect accesses happen.
+        bool range_cond = (info->_max < 0 || info->_max + min_jint <= info->_min);
+
+        // Generate code only if more than 2 range checks can be eliminated because of that.
+        // 2 because at least 2 comparisons are done
+        if (info->_list->length() > 2 && range_cond) {
+          AccessIndexed *first = info->_list->at(0);
+          Instruction *insert_position = first->prev();
+          assert(insert_position->next() == first, "prev was calculated");
+          ValueStack *state = first->state_before();
+
+          // Load min Constant
+          Constant *min_constant = NULL;
+          if (info->_min != 0) {
+            min_constant = new Constant(new IntConstant(info->_min));
+            NOT_PRODUCT(min_constant->set_printable_bci(first->printable_bci()));
+            insert_position = insert_position->insert_after(min_constant);
+          }
+
+          // Load max Constant
+          Constant *max_constant = NULL;
+          if (info->_max != 0) {
+            max_constant = new Constant(new IntConstant(info->_max));
+            NOT_PRODUCT(max_constant->set_printable_bci(first->printable_bci()));
+            insert_position = insert_position->insert_after(max_constant);
+          }
+
+          // Load array length
+          Value length_instr = first->length();
+          if (!length_instr) {
+            ArrayLength *length = new ArrayLength(array, first->state_before()->copy());
+            length->set_exception_state(length->state_before());
+            length->set_flag(Instruction::DeoptimizeOnException, true);
+            insert_position = insert_position->insert_after_same_bci(length);
+            length_instr = length;
+          }
+
+          // Calculate lower bound
+          Instruction *lower_compare = index_instruction;
+          if (min_constant) {
+            ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, min_constant, lower_compare, false, NULL);
+            insert_position = insert_position->insert_after_same_bci(ao);
+            lower_compare = ao;
+          }
+
+          // Calculate upper bound
+          Instruction *upper_compare = index_instruction;
+          if (max_constant) {
+            ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, max_constant, upper_compare, false, NULL);
+            insert_position = insert_position->insert_after_same_bci(ao);
+            upper_compare = ao;
+          }
+
+          // Trick with unsigned compare is done
+          int bci = NOT_PRODUCT(first->printable_bci()) PRODUCT_ONLY(-1);
+          insert_position = predicate(upper_compare, Instruction::aeq, length_instr, state, insert_position, bci);
+          insert_position = predicate_cmp_with_const(lower_compare, Instruction::leq, -1, state, insert_position);
+          for (int j = 0; j<info->_list->length(); j++) {
+            AccessIndexed *ai = info->_list->at(j);
+            remove_range_check(ai);
+          }
+        }
+        _access_indexed_info[index_instruction->id()] = NULL;
+      }
+      indices.clear();
+
+      if (list_constant.length() > 1) {
+        AccessIndexed *first = list_constant.at(0);
+        Instruction *insert_position = first->prev();
+        ValueStack *state = first->state_before();
+        // Load max Constant
+        Constant *constant = new Constant(new IntConstant(max_constant));
+        NOT_PRODUCT(constant->set_printable_bci(first->printable_bci()));
+        insert_position = insert_position->insert_after(constant);
+        Instruction *compare_instr = constant;
+        Value length_instr = first->length();
+        if (!length_instr) {
+          ArrayLength *length = new ArrayLength(array, state->copy());
+          length->set_exception_state(length->state_before());
+          length->set_flag(Instruction::DeoptimizeOnException, true);
+          insert_position = insert_position->insert_after_same_bci(length);
+          length_instr = length;
+        }
+        // Compare for greater or equal to array length
+        insert_position = predicate(compare_instr, Instruction::geq, length_instr, state, insert_position);
+        for (int j = 0; j<list_constant.length(); j++) {
+          AccessIndexed *ai = list_constant.at(j);
+          remove_range_check(ai);
+        }
+      }
+    }
+  }
+}
+
+bool RangeCheckEliminator::set_process_block_flags(BlockBegin *block) {
+  Instruction *cur = block;
+  bool process = false;
+
+  while (cur) {
+    process |= (cur->as_AccessIndexed() != NULL);
+    cur = cur->next();
+  }
+
+  BlockList *dominates = block->dominates();
+  for (int i=0; i<dominates->length(); i++) {
+    BlockBegin *next = dominates->at(i);
+    process |= set_process_block_flags(next);
+  }
+
+  if (!process) {
+    block->set(BlockBegin::donot_eliminate_range_checks);
+  }
+  return process;
+}
+
+bool RangeCheckEliminator::is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr, Instruction *length_instr, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper) {
+  bool upper_check = true;
+  assert(lower_instr || lower >= 0, "If no lower_instr present, lower must be greater 0");
+  assert(!lower_instr || lower_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller");
+  assert(!upper_instr || upper_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller");
+  assert(array_instr, "Array instruction must exist");
+  assert(array_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller");
+  assert(!length_instr || length_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller");
+
+  if (upper_instr && upper_instr->as_ArrayLength() && upper_instr->as_ArrayLength()->array() == array_instr) {
+    // static check
+    if (upper >= 0) return false; // would always trigger a deopt:
+                                  // array_length + x >= array_length, x >= 0 is always true
+    upper_check = false;
+  }
+  if (lower_instr && lower_instr->as_ArrayLength() && lower_instr->as_ArrayLength()->array() == array_instr) {
+    if (lower > 0) return false;
+  }
+  // No upper check required -> skip
+  if (upper_check && upper_instr && upper_instr->type()->as_ObjectType() && upper_instr == array_instr) {
+    // upper_instr is object means that the upper bound is the length
+    // of the upper_instr.
+    return false;
+  }
+  return true;
+}
+
+Instruction* RangeCheckEliminator::insert_after(Instruction* insert_position, Instruction* instr, int bci) {
+  if (bci != -1) {
+    NOT_PRODUCT(instr->set_printable_bci(bci));
+    return insert_position->insert_after(instr);
+  } else {
+    return insert_position->insert_after_same_bci(instr);
+  }
+}
+
+Instruction* RangeCheckEliminator::predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci) {
+  RangeCheckPredicate *deoptimize = new RangeCheckPredicate(left, cond, true, right, state->copy());
+  return insert_after(insert_position, deoptimize, bci);
+}
+
+Instruction* RangeCheckEliminator::predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci) {
+  Constant *const_instr = new Constant(new IntConstant(constant));
+  insert_position = insert_after(insert_position, const_instr, bci);
+  return predicate(instr, cond, const_instr, state, insert_position);
+}
+
+Instruction* RangeCheckEliminator::predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci) {
+  Constant *constant = new Constant(new IntConstant(left_const));
+  insert_position = insert_after(insert_position, constant, bci);
+  ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, left, false, NULL);
+  insert_position = insert_position->insert_after_same_bci(ao);
+  return predicate(ao, cond, right, state, insert_position);
+}
+
+Instruction* RangeCheckEliminator::predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci) {
+  Constant *const_instr = new Constant(new IntConstant(constant));
+  insert_position = insert_after(insert_position, const_instr, bci);
+  return predicate_add(left, left_const, cond, const_instr, state, insert_position);
+}
+
+// Insert deoptimization
+void RangeCheckEliminator::insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr, Instruction *length_instr, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper, AccessIndexed *ai) {
+  assert(is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, lower, upper_instr, upper), "should have been tested before");
+  bool upper_check = !(upper_instr && upper_instr->as_ArrayLength() && upper_instr->as_ArrayLength()->array() == array_instr);
+
+  int bci = NOT_PRODUCT(ai->printable_bci()) PRODUCT_ONLY(-1);
+  if (lower_instr) {
+    assert(!lower_instr->type()->as_ObjectType(), "Must not be object type");
+    if (lower == 0) {
+      // Compare for less than 0
+      insert_position = predicate_cmp_with_const(lower_instr, Instruction::lss, 0, state, insert_position, bci);
+    } else if (lower > 0) {
+      // Compare for smaller 0
+      insert_position = predicate_add_cmp_with_const(lower_instr, lower, Instruction::lss, 0, state, insert_position, bci);
+    } else {
+      assert(lower < 0, "");
+      // Add 1
+      lower++;
+      lower = -lower;
+      // Compare for smaller or equal 0
+      insert_position = predicate_cmp_with_const(lower_instr, Instruction::leq, lower, state, insert_position, bci);
+    }
+  }
+
+  // No upper check required -> skip
+  if (!upper_check) return;
+
+  // We need to know length of array
+  if (!length_instr) {
+    // Load length if necessary
+    ArrayLength *length = new ArrayLength(array_instr, state->copy());
+    NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()));
+    length->set_exception_state(length->state_before());
+    length->set_flag(Instruction::DeoptimizeOnException, true);
+    insert_position = insert_position->insert_after(length);
+    length_instr = length;
+  }
+
+  if (!upper_instr) {
+    // Compare for geq array.length
+    insert_position = predicate_cmp_with_const(length_instr, Instruction::leq, upper, state, insert_position, bci);
+  } else {
+    if (upper_instr->type()->as_ObjectType()) {
+      assert(state, "must not be null");
+      assert(upper_instr != array_instr, "should be");
+      ArrayLength *length = new ArrayLength(upper_instr, state->copy());
+      NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()));
+      length->set_flag(Instruction::DeoptimizeOnException, true);
+      length->set_exception_state(length->state_before());
+      insert_position = insert_position->insert_after(length);
+      upper_instr = length;
+    }
+    assert(upper_instr->type()->as_IntType(), "Must not be object type!");
+
+    if (upper == 0) {
+      // Compare for geq array.length
+      insert_position = predicate(upper_instr, Instruction::geq, length_instr, state, insert_position, bci);
+    } else if (upper < 0) {
+      // Compare for geq array.length
+      insert_position = predicate_add(upper_instr, upper, Instruction::geq, length_instr, state, insert_position, bci);
+    } else {
+      assert(upper > 0, "");
+      upper = -upper;
+      // Compare for geq array.length
+      insert_position = predicate_add(length_instr, upper, Instruction::leq, upper_instr, state, insert_position, bci);
+    }
+  }
+}
+
+// Add if condition
+void RangeCheckEliminator::add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition) {
+  if (y->as_Constant()) return;
+
+  int const_value = 0;
+  Value instr_value = x;
+  Constant *c = x->as_Constant();
+  ArithmeticOp *ao = x->as_ArithmeticOp();
+
+  if (c != NULL) {
+    const_value = c->type()->as_IntConstant()->value();
+    instr_value = NULL;
+  } else if (ao != NULL &&  (!ao->x()->as_Constant() || !ao->y()->as_Constant()) && ((ao->op() == Bytecodes::_isub && ao->y()->as_Constant()) || ao->op() == Bytecodes::_iadd)) {
+    assert(!ao->x()->as_Constant() || !ao->y()->as_Constant(), "At least one operator must be non-constant!");
+    assert(ao->op() == Bytecodes::_isub || ao->op() == Bytecodes::_iadd, "Operation has to be add or sub!");
+    c = ao->x()->as_Constant();
+    if (c != NULL) {
+      const_value = c->type()->as_IntConstant()->value();
+      instr_value = ao->y();
+    } else {
+      c = ao->y()->as_Constant();
+      if (c != NULL) {
+        const_value = c->type()->as_IntConstant()->value();
+        instr_value = ao->x();
+      }
+    }
+    if (ao->op() == Bytecodes::_isub) {
+      assert(ao->y()->as_Constant(), "1 - x not supported, only x - 1 is valid!");
+      if (const_value > min_jint) {
+        const_value = -const_value;
+      } else {
+        const_value = 0;
+        instr_value = x;
+      }
+    }
+  }
+
+  update_bound(pushed, y, condition, instr_value, const_value);
+}
+
+// Process If
+void RangeCheckEliminator::process_if(IntegerStack &pushed, BlockBegin *block, If *cond) {
+  // Only if we are direct true / false successor and NOT both ! (even this may occur)
+  if ((cond->tsux() == block || cond->fsux() == block) && cond->tsux() != cond->fsux()) {
+    Instruction::Condition condition = cond->cond();
+    if (cond->fsux() == block) {
+      condition = Instruction::negate(condition);
+    }
+    Value x = cond->x();
+    Value y = cond->y();
+    if (x->type()->as_IntType() && y->type()->as_IntType()) {
+      add_if_condition(pushed, y, x, condition);
+      add_if_condition(pushed, x, y, Instruction::mirror(condition));
+    }
+  }
+}
+
+// Process access indexed
+void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai) {
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->fill_to(block->dominator_depth()*2)
+  );
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->print_cr("Access indexed: index=%d length=%d", ai->index()->id(), (ai->length() != NULL ? ai->length()->id() :-1 ))
+  );
+
+  if (ai->check_flag(Instruction::NeedsRangeCheckFlag)) {
+    Bound *index_bound = get_bound(ai->index());
+    if (!index_bound->has_lower() || !index_bound->has_upper()) {
+      TRACE_RANGE_CHECK_ELIMINATION(
+        tty->fill_to(block->dominator_depth()*2);
+        tty->print_cr("Index instruction %d has no lower and/or no upper bound!", ai->index()->id())
+      );
+      return;
+    }
+
+    Bound *array_bound;
+    if (ai->length()) {
+      array_bound = get_bound(ai->length());
+    } else {
+      array_bound = get_bound(ai->array());
+    }
+
+    if (in_array_bound(index_bound, ai->array()) ||
+      (index_bound && array_bound && index_bound->is_smaller(array_bound) && !index_bound->lower_instr() && index_bound->lower() >= 0)) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!", ai->id(), ai->block()->block_id())
+        );
+
+        remove_range_check(ai);
+    } else if (_optimistic && loop_header) {
+      assert(ai->array(), "Array must not be null!");
+      assert(ai->index(), "Index must not be null!");
+
+      // Array instruction
+      Instruction *array_instr = ai->array();
+      if (!loop_invariant(loop_header, array_instr)) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Array %d is not loop invariant to header B%d", ai->array()->id(), loop_header->block_id())
+        );
+        return;
+      }
+
+      // Lower instruction
+      Value index_instr = ai->index();
+      Value lower_instr = index_bound->lower_instr();
+      if (!loop_invariant(loop_header, lower_instr)) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Lower instruction %d not loop invariant!", lower_instr->id())
+        );
+        return;
+      }
+      if (!lower_instr && index_bound->lower() < 0) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound->lower())
+        );
+        return;
+      }
+
+      // Upper instruction
+      Value upper_instr = index_bound->upper_instr();
+      if (!loop_invariant(loop_header, upper_instr)) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Upper instruction %d not loop invariant!", upper_instr->id())
+        );
+        return;
+      }
+
+      // Length instruction
+      Value length_instr = ai->length();
+      if (!loop_invariant(loop_header, length_instr)) {
+        // Generate length instruction yourself!
+        length_instr = NULL;
+      }
+
+      TRACE_RANGE_CHECK_ELIMINATION(
+        tty->fill_to(block->dominator_depth()*2);
+        tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!", ai->id(), ai->block()->block_id())
+      );
+
+      BlockBegin *pred_block = loop_header->dominator();
+      assert(pred_block != NULL, "Every loop header has a dominator!");
+      BlockEnd *pred_block_end = pred_block->end();
+      Instruction *insert_position = pred_block_end->prev();
+      ValueStack *state = pred_block_end->state_before();
+      if (pred_block_end->as_Goto() && state == NULL) state = pred_block_end->state();
+      assert(state, "State must not be null");
+
+      // Add deoptimization to dominator of loop header
+      TRACE_RANGE_CHECK_ELIMINATION(
+        tty->fill_to(block->dominator_depth()*2);
+        tty->print_cr("Inserting deopt at bci %d in block B%d!", state->bci(), insert_position->block()->block_id())
+      );
+
+      if (!is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper())) {
+        TRACE_RANGE_CHECK_ELIMINATION(
+          tty->fill_to(block->dominator_depth()*2);
+          tty->print_cr("Could not eliminate because of static analysis!")
+        );
+        return;
+      }
+
+      insert_deoptimization(state, insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper(), ai);
+
+      // Finally remove the range check!
+      remove_range_check(ai);
+    }
+  }
+}
+
+void RangeCheckEliminator::remove_range_check(AccessIndexed *ai) {
+  ai->set_flag(Instruction::NeedsRangeCheckFlag, false);
+  // no range check, no need for the length instruction anymore
+  ai->clear_length();
+
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->fill_to(ai->dominator_depth()*2);
+    tty->print_cr("Range check for instruction %d eliminated!", ai->id());
+  );
+
+  ASSERT_RANGE_CHECK_ELIMINATION(
+    Value array_length = ai->length();
+    if (!array_length) {
+      array_length = ai->array();
+      assert(array_length->type()->as_ObjectType(), "Has to be object type!");
+    }
+    int cur_constant = -1;
+    Value cur_value = array_length;
+    if (cur_value->type()->as_IntConstant()) {
+      cur_constant += cur_value->type()->as_IntConstant()->value();
+      cur_value = NULL;
+    }
+    Bound *new_index_bound = new Bound(0, NULL, cur_constant, cur_value);
+    add_assertions(new_index_bound, ai->index(), ai);
+  );
+}
+
+// Calculate bounds for instruction in this block and children blocks in the dominator tree
+void RangeCheckEliminator::calc_bounds(BlockBegin *block, BlockBegin *loop_header) {
+  // Ensures a valid loop_header
+  assert(!loop_header || loop_header->is_set(BlockBegin::linear_scan_loop_header_flag), "Loop header has to be real !");
+
+  // Tracing output
+  TRACE_RANGE_CHECK_ELIMINATION(
+    tty->fill_to(block->dominator_depth()*2);
+    tty->print_cr("Block B%d", block->block_id());
+  );
+
+  // Pushed stack for conditions
+  IntegerStack pushed;
+  // Process If
+  BlockBegin *parent = block->dominator();
+  if (parent != NULL) {
+    If *cond = parent->end()->as_If();
+    if (cond != NULL) {
+      process_if(pushed, block, cond);
+    }
+  }
+
+  // Interate over current block
+  InstructionList arrays;
+  AccessIndexedList accessIndexed;
+  Instruction *cur = block;
+
+  while (cur) {
+    // Ensure cur wasn't inserted during the elimination
+    if (cur->id() < this->_bounds.length()) {
+      // Process only if it is an access indexed instruction
+      AccessIndexed *ai = cur->as_AccessIndexed();
+      if (ai != NULL) {
+        process_access_indexed(loop_header, block, ai);
+        accessIndexed.append(ai);
+        if (!arrays.contains(ai->array())) {
+          arrays.append(ai->array());
+        }
+        Bound *b = get_bound(ai->index());
+        if (!b->lower_instr()) {
+          // Lower bound is constant
+          update_bound(pushed, ai->index(), Instruction::geq, NULL, 0);
+        }
+        if (!b->has_upper()) {
+          if (ai->length() && ai->length()->type()->as_IntConstant()) {
+            int value = ai->length()->type()->as_IntConstant()->value();
+            update_bound(pushed, ai->index(), Instruction::lss, NULL, value);
+          } else {
+            // Has no upper bound
+            Instruction *instr = ai->length();
+            if (instr != NULL) instr = ai->array();
+            update_bound(pushed, ai->index(), Instruction::lss, instr, 0);
+          }
+        }
+      }
+    }
+    cur = cur->next();
+  }
+
+  // Output current condition stack
+  TRACE_RANGE_CHECK_ELIMINATION(dump_condition_stack(block));
+
+  // Do in block motion of range checks
+  in_block_motion(block, accessIndexed, arrays);
+
+  // Call all dominated blocks
+  for (int i=0; i<block->dominates()->length(); i++) {
+    BlockBegin *next = block->dominates()->at(i);
+    if (!next->is_set(BlockBegin::donot_eliminate_range_checks)) {
+      // if current block is a loop header and:
+      // - next block belongs to the same loop
+      // or
+      // - next block belongs to an inner loop
+      // then current block is the loop header for next block
+      if (block->is_set(BlockBegin::linear_scan_loop_header_flag) && (block->loop_index() == next->loop_index() || next->loop_depth() > block->loop_depth())) {
+        calc_bounds(next, block);
+      } else {
+        calc_bounds(next, loop_header);
+      }
+    }
+  }
+
+  // Reset stack
+  for (int i=0; i<pushed.length(); i++) {
+    _bounds[pushed[i]]->pop();
+  }
+}
+
+#ifndef PRODUCT
+// Dump condition stack
+void RangeCheckEliminator::dump_condition_stack(BlockBegin *block) {
+  for (int i=0; i<_ir->linear_scan_order()->length(); i++) {
+    BlockBegin *cur_block = _ir->linear_scan_order()->at(i);
+    Instruction *instr = cur_block;
+    for_each_phi_fun(cur_block, phi,
+                     BoundStack *bound_stack = _bounds.at(phi->id());
+                     if (bound_stack && bound_stack->length() > 0) {
+                       Bound *bound = bound_stack->top();
+                       if ((bound->has_lower() || bound->has_upper()) && (bound->lower_instr() != phi || bound->upper_instr() != phi || bound->lower() != 0 || bound->upper() != 0)) {
+                           TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());
+                                                         tty->print("i%d", phi->id());
+                                                         tty->print(": ");
+                                                         bound->print();
+                                                         tty->print_cr("");
+                           );
+                         }
+                     });
+
+    while (!instr->as_BlockEnd()) {
+      if (instr->id() < _bounds.length()) {
+        BoundStack *bound_stack = _bounds.at(instr->id());
+        if (bound_stack && bound_stack->length() > 0) {
+          Bound *bound = bound_stack->top();
+          if ((bound->has_lower() || bound->has_upper()) && (bound->lower_instr() != instr || bound->upper_instr() != instr || bound->lower() != 0 || bound->upper() != 0)) {
+              TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());
+                                            tty->print("i%d", instr->id());
+                                            tty->print(": ");
+                                            bound->print();
+                                            tty->print_cr("");
+              );
+          }
+        }
+      }
+      instr = instr->next();
+    }
+  }
+}
+#endif
+
+// Verification or the IR
+RangeCheckEliminator::Verification::Verification(IR *ir) : _used(BlockBegin::number_of_blocks(), false) {
+  this->_ir = ir;
+  ir->iterate_linear_scan_order(this);
+}
+
+// Verify this block
+void RangeCheckEliminator::Verification::block_do(BlockBegin *block) {
+  If *cond = block->end()->as_If();
+  // Watch out: tsux and fsux can be the same!
+  if (block->number_of_sux() > 1) {
+    for (int i=0; i<block->number_of_sux(); i++) {
+      BlockBegin *sux = block->sux_at(i);
+      BlockBegin *pred = NULL;
+      for (int j=0; j<sux->number_of_preds(); j++) {
+        BlockBegin *cur = sux->pred_at(j);
+        assert(cur != NULL, "Predecessor must not be null");
+        if (!pred) {
+          pred = cur;
+        }
+        assert(cur == pred, "Block must not have more than one predecessor if its predecessor has more than one successor");
+      }
+      assert(sux->number_of_preds() >= 1, "Block must have at least one predecessor");
+      assert(sux->pred_at(0) == block, "Wrong successor");
+    }
+  }
+
+  BlockBegin *dominator = block->dominator();
+  if (dominator) {
+    assert(block != _ir->start(), "Start block must not have a dominator!");
+    assert(can_reach(dominator, block), "Dominator can't reach his block !");
+    assert(can_reach(_ir->start(), dominator), "Dominator is unreachable !");
+    assert(!can_reach(_ir->start(), block, dominator), "Wrong dominator ! Block can be reached anyway !");
+    BlockList *all_blocks = _ir->linear_scan_order();
+    for (int i=0; i<all_blocks->length(); i++) {
+      BlockBegin *cur = all_blocks->at(i);
+      if (cur != dominator && cur != block) {
+        assert(can_reach(dominator, block, cur), "There has to be another dominator!");
+      }
+    }
+  } else {
+    assert(block == _ir->start(), "Only start block must not have a dominator");
+  }
+
+  if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
+    int loop_index = block->loop_index();
+    BlockList *all_blocks = _ir->linear_scan_order();
+    assert(block->number_of_preds() >= 1, "Block must have at least one predecessor");
+    assert(!block->is_set(BlockBegin::exception_entry_flag), "Loop header must not be exception handler!");
+    // Sometimes, the backbranch comes from an exception handler. In
+    // this case, loop indexes/loop depths may not appear correct.
+    bool loop_through_xhandler = false;
+    for (int i = 0; i < block->number_of_exception_handlers(); i++) {
+      BlockBegin *xhandler = block->exception_handler_at(i);
+      for (int j = 0; j < block->number_of_preds(); j++) {
+        if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) {
+          loop_through_xhandler = true;
+        }
+      }
+    }
+
+    for (int i=0; i<block->number_of_sux(); i++) {
+      BlockBegin *sux = block->sux_at(i);
+      assert(sux->loop_depth() != block->loop_depth() || sux->loop_index() == block->loop_index() || loop_through_xhandler, "Loop index has to be same");
+      assert(sux->loop_depth() == block->loop_depth() || sux->loop_index() != block->loop_index(), "Loop index has to be different");
+    }
+
+    for (int i=0; i<all_blocks->length(); i++) {
+      BlockBegin *cur = all_blocks->at(i);
+      if (cur->loop_index() == loop_index && cur != block) {
+        assert(dominates(block->dominator(), cur), "Dominator of loop header must dominate all loop blocks");
+      }
+    }
+  }
+
+  Instruction *cur = block;
+  while (cur) {
+    assert(cur->block() == block, "Block begin has to be set correctly!");
+    cur = cur->next();
+  }
+}
+
+// Loop header must dominate all loop blocks
+bool RangeCheckEliminator::Verification::dominates(BlockBegin *dominator, BlockBegin *block) {
+  BlockBegin *cur = block->dominator();
+  while (cur && cur != dominator) {
+    cur = cur->dominator();
+  }
+  return cur == dominator;
+}
+
+// Try to reach Block end beginning in Block start and not using Block dont_use
+bool RangeCheckEliminator::Verification::can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use /* = NULL */) {
+  if (start == end) return start != dont_use;
+  // Simple BSF from start to end
+  //  BlockBeginList _current;
+  for (int i=0; i<_used.length(); i++) {
+    _used[i] = false;
+  }
+  _current.truncate(0);
+  _successors.truncate(0);
+  if (start != dont_use) {
+    _current.push(start);
+    _used[start->block_id()] = true;
+  }
+
+  //  BlockBeginList _successors;
+  while (_current.length() > 0) {
+    BlockBegin *cur = _current.pop();
+    // Add exception handlers to list
+    for (int i=0; i<cur->number_of_exception_handlers(); i++) {
+      BlockBegin *xhandler = cur->exception_handler_at(i);
+      _successors.push(xhandler);
+      // Add exception handlers of _successors to list
+      for (int j=0; j<xhandler->number_of_exception_handlers(); j++) {
+        BlockBegin *sux_xhandler = xhandler->exception_handler_at(j);
+        _successors.push(sux_xhandler);
+      }
+    }
+    // Add normal _successors to list
+    for (int i=0; i<cur->number_of_sux(); i++) {
+      BlockBegin *sux = cur->sux_at(i);
+      _successors.push(sux);
+      // Add exception handlers of _successors to list
+      for (int j=0; j<sux->number_of_exception_handlers(); j++) {
+        BlockBegin *xhandler = sux->exception_handler_at(j);
+        _successors.push(xhandler);
+      }
+    }
+    for (int i=0; i<_successors.length(); i++) {
+      BlockBegin *sux = _successors[i];
+      assert(sux != NULL, "Successor must not be NULL!");
+      if (sux == end) {
+        return true;
+      }
+      if (sux != dont_use && !_used[sux->block_id()]) {
+        _used[sux->block_id()] = true;
+        _current.push(sux);
+      }
+    }
+    _successors.truncate(0);
+  }
+
+  return false;
+}
+
+// Bound
+RangeCheckEliminator::Bound::~Bound() {
+}
+
+// Bound constructor
+RangeCheckEliminator::Bound::Bound() {
+  init();
+  this->_lower = min_jint;
+  this->_upper = max_jint;
+  this->_lower_instr = NULL;
+  this->_upper_instr = NULL;
+}
+
+// Bound constructor
+RangeCheckEliminator::Bound::Bound(int lower, Value lower_instr, int upper, Value upper_instr) {
+  init();
+  assert(!lower_instr || !lower_instr->as_Constant() || !lower_instr->type()->as_IntConstant(), "Must not be constant!");
+  assert(!upper_instr || !upper_instr->as_Constant() || !upper_instr->type()->as_IntConstant(), "Must not be constant!");
+  this->_lower = lower;
+  this->_upper = upper;
+  this->_lower_instr = lower_instr;
+  this->_upper_instr = upper_instr;
+}
+
+// Bound constructor
+RangeCheckEliminator::Bound::Bound(Instruction::Condition cond, Value v, int constant) {
+  assert(!v || (v->type() && (v->type()->as_IntType() || v->type()->as_ObjectType())), "Type must be array or integer!");
+  assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!");
+
+  init();
+  if (cond == Instruction::eql) {
+    _lower = constant;
+    _lower_instr = v;
+    _upper = constant;
+    _upper_instr = v;
+  } else if (cond == Instruction::neq) {
+    _lower = min_jint;
+    _upper = max_jint;
+    _lower_instr = NULL;
+    _upper_instr = NULL;
+    if (v == NULL) {
+      if (constant == min_jint) {
+        _lower++;
+      }
+      if (constant == max_jint) {
+        _upper--;
+      }
+    }
+  } else if (cond == Instruction::geq) {
+    _lower = constant;
+    _lower_instr = v;
+    _upper = max_jint;
+    _upper_instr = NULL;
+  } else if (cond == Instruction::leq) {
+    _lower = min_jint;
+    _lower_instr = NULL;
+    _upper = constant;
+    _upper_instr = v;
+  } else {
+    ShouldNotReachHere();
+  }
+}
+
+// Set lower
+void RangeCheckEliminator::Bound::set_lower(int value, Value v) {
+  assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!");
+  this->_lower = value;
+  this->_lower_instr = v;
+}
+
+// Set upper
+void RangeCheckEliminator::Bound::set_upper(int value, Value v) {
+  assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!");
+  this->_upper = value;
+  this->_upper_instr = v;
+}
+
+// Add constant -> no overflow may occur
+void RangeCheckEliminator::Bound::add_constant(int value) {
+  this->_lower += value;
+  this->_upper += value;
+}
+
+// Init
+void RangeCheckEliminator::Bound::init() {
+}
+
+// or
+void RangeCheckEliminator::Bound::or_op(Bound *b) {
+  // Watch out, bound is not guaranteed not to overflow!
+  // Update lower bound
+  if (_lower_instr != b->_lower_instr || (_lower_instr && _lower != b->_lower)) {
+    _lower_instr = NULL;
+    _lower = min_jint;
+  } else {
+    _lower = MIN2(_lower, b->_lower);
+  }
+  // Update upper bound
+  if (_upper_instr != b->_upper_instr || (_upper_instr && _upper != b->_upper)) {
+    _upper_instr = NULL;
+    _upper = max_jint;
+  } else {
+    _upper = MAX2(_upper, b->_upper);
+  }
+}
+
+// and
+void RangeCheckEliminator::Bound::and_op(Bound *b) {
+  // Update lower bound
+  if (_lower_instr == b->_lower_instr) {
+    _lower = MAX2(_lower, b->_lower);
+  }
+  if (b->has_lower()) {
+    bool set = true;
+    if (_lower_instr != NULL && b->_lower_instr != NULL) {
+      set = (_lower_instr->dominator_depth() > b->_lower_instr->dominator_depth());
+    }
+    if (set) {
+      _lower = b->_lower;
+      _lower_instr = b->_lower_instr;
+    }
+  }
+  // Update upper bound
+  if (_upper_instr == b->_upper_instr) {
+    _upper = MIN2(_upper, b->_upper);
+  }
+  if (b->has_upper()) {
+    bool set = true;
+    if (_upper_instr != NULL && b->_upper_instr != NULL) {
+      set = (_upper_instr->dominator_depth() > b->_upper_instr->dominator_depth());
+    }
+    if (set) {
+      _upper = b->_upper;
+      _upper_instr = b->_upper_instr;
+    }
+  }
+}
+
+// has_upper
+bool RangeCheckEliminator::Bound::has_upper() {
+  return _upper_instr != NULL || _upper < max_jint;
+}
+
+// is_smaller
+bool RangeCheckEliminator::Bound::is_smaller(Bound *b) {
+  if (b->_lower_instr != _upper_instr) {
+    return false;
+  }
+  return _upper < b->_lower;
+}
+
+// has_lower
+bool RangeCheckEliminator::Bound::has_lower() {
+  return _lower_instr != NULL || _lower > min_jint;
+}
+
+// in_array_bound
+bool RangeCheckEliminator::in_array_bound(Bound *bound, Value array){
+  if (!bound) return false;
+  assert(array != NULL, "Must not be null!");
+  assert(bound != NULL, "Must not be null!");
+  if (bound->lower() >=0 && bound->lower_instr() == NULL && bound->upper() < 0 && bound->upper_instr() != NULL) {
+    ArrayLength *len = bound->upper_instr()->as_ArrayLength();
+    if (bound->upper_instr() == array || (len != NULL && len->array() == array)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// remove_lower
+void RangeCheckEliminator::Bound::remove_lower() {
+  _lower = min_jint;
+  _lower_instr = NULL;
+}
+
+// remove_upper
+void RangeCheckEliminator::Bound::remove_upper() {
+  _upper = max_jint;
+  _upper_instr = NULL;
+}
+
+// upper
+int RangeCheckEliminator::Bound::upper() {
+  return _upper;
+}
+
+// lower
+int RangeCheckEliminator::Bound::lower() {
+  return _lower;
+}
+
+// upper_instr
+Value RangeCheckEliminator::Bound::upper_instr() {
+  return _upper_instr;
+}
+
+// lower_instr
+Value RangeCheckEliminator::Bound::lower_instr() {
+  return _lower_instr;
+}
+
+// print
+void RangeCheckEliminator::Bound::print() {
+  tty->print("");
+  if (this->_lower_instr || this->_lower != min_jint) {
+    if (this->_lower_instr) {
+      tty->print("i%d", this->_lower_instr->id());
+      if (this->_lower > 0) {
+        tty->print("+%d", _lower);
+      }
+      if (this->_lower < 0) {
+        tty->print("%d", _lower);
+      }
+    } else {
+      tty->print("%d", _lower);
+    }
+    tty->print(" <= ");
+  }
+  tty->print("x");
+  if (this->_upper_instr || this->_upper != max_jint) {
+    tty->print(" <= ");
+    if (this->_upper_instr) {
+      tty->print("i%d", this->_upper_instr->id());
+      if (this->_upper > 0) {
+        tty->print("+%d", _upper);
+      }
+      if (this->_upper < 0) {
+        tty->print("%d", _upper);
+      }
+    } else {
+      tty->print("%d", _upper);
+    }
+  }
+}
+
+// Copy
+RangeCheckEliminator::Bound *RangeCheckEliminator::Bound::copy() {
+  Bound *b = new Bound();
+  b->_lower = _lower;
+  b->_lower_instr = _lower_instr;
+  b->_upper = _upper;
+  b->_upper_instr = _upper_instr;
+  return b;
+}
+
+#ifdef ASSERT
+// Add assertion
+void RangeCheckEliminator::Bound::add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond) {
+  Instruction *result = position;
+  Instruction *compare_with = NULL;
+  ValueStack *state = position->state_before();
+  if (position->as_BlockEnd() && !position->as_Goto()) {
+    state = position->as_BlockEnd()->state_before();
+  }
+  Instruction *instruction_before = position->prev();
+  if (position->as_Return() && Compilation::current()->method()->is_synchronized() && instruction_before->as_MonitorExit()) {
+    instruction_before = instruction_before->prev();
+  }
+  result = instruction_before;
+  // Load constant only if needed
+  Constant *constant = NULL;
+  if (i != 0 || !instr) {
+    constant = new Constant(new IntConstant(i));
+    NOT_PRODUCT(constant->set_printable_bci(position->printable_bci()));
+    result = result->insert_after(constant);
+    compare_with = constant;
+  }
+
+  if (instr) {
+    assert(instr->type()->as_ObjectType() || instr->type()->as_IntType(), "Type must be array or integer!");
+    compare_with = instr;
+    // Load array length if necessary
+    Instruction *op = instr;
+    if (instr->type()->as_ObjectType()) {
+      assert(state, "must not be null");
+      ArrayLength *length = new ArrayLength(instr, state->copy());
+      NOT_PRODUCT(length->set_printable_bci(position->printable_bci()));
+      length->set_exception_state(length->state_before());
+      result = result->insert_after(length);
+      op = length;
+      compare_with = length;
+    }
+    // Add operation only if necessary
+    if (constant) {
+      ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, op, false, NULL);
+      NOT_PRODUCT(ao->set_printable_bci(position->printable_bci()));
+      result = result->insert_after(ao);
+      compare_with = ao;
+      // TODO: Check that add operation does not overflow!
+    }
+  }
+  assert(compare_with != NULL, "You have to compare with something!");
+  assert(instruction != NULL, "Instruction must not be null!");
+
+  if (instruction->type()->as_ObjectType()) {
+    // Load array length if necessary
+    Instruction *op = instruction;
+    assert(state, "must not be null");
+    ArrayLength *length = new ArrayLength(instruction, state->copy());
+    length->set_exception_state(length->state_before());
+    NOT_PRODUCT(length->set_printable_bci(position->printable_bci()));
+    result = result->insert_after(length);
+    instruction = length;
+  }
+
+  Assert *assert = new Assert(instruction, cond, false, compare_with);
+  NOT_PRODUCT(assert->set_printable_bci(position->printable_bci()));
+  result->insert_after(assert);
+}
+
+// Add assertions
+void RangeCheckEliminator::add_assertions(Bound *bound, Instruction *instruction, Instruction *position) {
+  // Add lower bound assertion
+  if (bound->has_lower()) {
+    bound->add_assertion(instruction, position, bound->lower(), bound->lower_instr(), Instruction::geq);
+  }
+  // Add upper bound assertion
+  if (bound->has_upper()) {
+    bound->add_assertion(instruction, position, bound->upper(), bound->upper_instr(), Instruction::leq);
+  }
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/c1/c1_RangeCheckElimination.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,241 @@
+/*
+ * 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_C1_C1_RANGECHECKELIMINATION_HPP
+#define SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP
+
+#include "c1/c1_Instruction.hpp"
+
+// Base class for range check elimination
+class RangeCheckElimination : AllStatic {
+public:
+  static void eliminate(IR *ir);
+};
+
+// Implementation
+class RangeCheckEliminator VALUE_OBJ_CLASS_SPEC {
+private:
+  int _number_of_instructions;
+  bool _optimistic; // Insert predicates and deoptimize when they fail
+  IR *_ir;
+
+  define_array(BlockBeginArray, BlockBegin*)
+  define_stack(BlockBeginList, BlockBeginArray)
+  define_stack(IntegerStack, intArray)
+  define_array(IntegerMap, IntegerStack*)
+
+  class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure {
+  private:
+    IR *_ir;
+    boolArray _used;
+    BlockBeginList _current;
+    BlockBeginList _successors;
+
+  public:
+    Verification(IR *ir);
+    virtual void block_do(BlockBegin *block);
+    bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL);
+    bool dominates(BlockBegin *dominator, BlockBegin *block);
+  };
+
+public:
+  // Bounds for an instruction in the form x + c which c integer
+  // constant and x another instruction
+  class Bound : public CompilationResourceObj {
+  private:
+    int _upper;
+    Value _upper_instr;
+    int _lower;
+    Value _lower_instr;
+
+  public:
+    Bound();
+    Bound(Value v);
+    Bound(Instruction::Condition cond, Value v, int constant = 0);
+    Bound(int lower, Value lower_instr, int upper, Value upper_instr);
+    ~Bound();
+
+#ifdef ASSERT
+    void add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond);
+#endif
+    int upper();
+    Value upper_instr();
+    int lower();
+    Value lower_instr();
+    void print();
+    bool check_no_overflow(int const_value);
+    void or_op(Bound *b);
+    void and_op(Bound *b);
+    bool has_upper();
+    bool has_lower();
+    void set_upper(int upper, Value upper_instr);
+    void set_lower(int lower, Value lower_instr);
+    bool is_smaller(Bound *b);
+    void remove_upper();
+    void remove_lower();
+    void add_constant(int value);
+    Bound *copy();
+
+  private:
+    void init();
+  };
+
+
+  class Visitor : public InstructionVisitor {
+  private:
+    Bound *_bound;
+    RangeCheckEliminator *_rce;
+
+  public:
+    void set_range_check_eliminator(RangeCheckEliminator *rce) { _rce = rce; }
+    Bound *bound() const { return _bound; }
+    void clear_bound() { _bound = NULL; }
+
+  protected:
+    // visitor functions
+    void do_Constant       (Constant*        x);
+    void do_IfOp           (IfOp*            x);
+    void do_LogicOp        (LogicOp*         x);
+    void do_ArithmeticOp   (ArithmeticOp*    x);
+    void do_Phi            (Phi*             x);
+
+    void do_StoreField     (StoreField*      x) { /* nothing to do */ };
+    void do_StoreIndexed   (StoreIndexed*    x) { /* nothing to do */ };
+    void do_MonitorEnter   (MonitorEnter*    x) { /* nothing to do */ };
+    void do_MonitorExit    (MonitorExit*     x) { /* nothing to do */ };
+    void do_Invoke         (Invoke*          x) { /* nothing to do */ };
+    void do_UnsafePutRaw   (UnsafePutRaw*    x) { /* nothing to do */ };
+    void do_UnsafePutObject(UnsafePutObject* x) { /* nothing to do */ };
+    void do_Intrinsic      (Intrinsic*       x) { /* nothing to do */ };
+    void do_Local          (Local*           x) { /* nothing to do */ };
+    void do_LoadField      (LoadField*       x) { /* nothing to do */ };
+    void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ };
+    void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ };
+    void do_NegateOp       (NegateOp*        x) { /* nothing to do */ };
+    void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ };
+    void do_CompareOp      (CompareOp*       x) { /* nothing to do */ };
+    void do_Convert        (Convert*         x) { /* nothing to do */ };
+    void do_NullCheck      (NullCheck*       x) { /* nothing to do */ };
+    void do_TypeCast       (TypeCast*        x) { /* nothing to do */ };
+    void do_NewInstance    (NewInstance*     x) { /* nothing to do */ };
+    void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ };
+    void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ };
+    void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ };
+    void do_CheckCast      (CheckCast*       x) { /* nothing to do */ };
+    void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ };
+    void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ };
+    void do_Goto           (Goto*            x) { /* nothing to do */ };
+    void do_If             (If*              x) { /* nothing to do */ };
+    void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ };
+    void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ };
+    void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ };
+    void do_Return         (Return*          x) { /* nothing to do */ };
+    void do_Throw          (Throw*           x) { /* nothing to do */ };
+    void do_Base           (Base*            x) { /* nothing to do */ };
+    void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ };
+    void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
+    void do_RoundFP        (RoundFP*         x) { /* nothing to do */ };
+    void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ };
+    void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
+    void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { /* nothing to do */ };
+    void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ };
+    void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ };
+    void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ };
+    void do_ProfileInvoke  (ProfileInvoke*  x)  { /* nothing to do */ };
+    void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
+    void do_MemBar         (MemBar*          x) { /* nothing to do */ };
+    void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ };
+    void do_Assert         (Assert*          x) { /* nothing to do */ };
+  };
+
+#ifdef ASSERT
+  void add_assertions(Bound *bound, Instruction *instruction, Instruction *position);
+#endif
+
+  define_array(BoundArray, Bound *)
+  define_stack(BoundStack, BoundArray)
+  define_array(BoundMap, BoundStack *)
+  define_array(AccessIndexedArray, AccessIndexed *)
+  define_stack(AccessIndexedList, AccessIndexedArray)
+  define_array(InstructionArray, Instruction *)
+  define_stack(InstructionList, InstructionArray)
+
+  class AccessIndexedInfo : public CompilationResourceObj  {
+  public:
+    AccessIndexedList *_list;
+    int _min;
+    int _max;
+  };
+
+  define_array(AccessIndexedInfoArray, AccessIndexedInfo *)
+  BoundMap _bounds; // Mapping from Instruction's id to current bound
+  AccessIndexedInfoArray _access_indexed_info; // Mapping from Instruction's id to AccessIndexedInfo for in block motion
+  Visitor _visitor;
+
+public:
+  RangeCheckEliminator(IR *ir);
+
+  IR *ir() const { return _ir; }
+
+  // Pass over the dominator tree to identify blocks where there's an oppportunity for optimization
+  bool set_process_block_flags(BlockBegin *block);
+  // The core of the optimization work: pass over the dominator tree
+  // to propagate bound information, insert predicate out of loops,
+  // eliminate bound checks when possible and perform in block motion
+  void calc_bounds(BlockBegin *block, BlockBegin *loop_header);
+  // reorder bound checks within a block in order to eliminate some of them
+  void in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays);
+
+  // update/access current bound
+  void update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant);
+  void update_bound(IntegerStack &pushed, Value v, Bound *bound);
+  Bound *get_bound(Value v);
+
+  bool loop_invariant(BlockBegin *loop_header, Instruction *instruction);                                    // check for loop invariance
+  void add_access_indexed_info(InstructionList &indices, int i, Value instruction, AccessIndexed *ai); // record indexed access for in block motion
+  void remove_range_check(AccessIndexed *ai);                                                                // Mark this instructions as not needing a range check
+  void add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition);           // Update bound for an If
+  bool in_array_bound(Bound *bound, Value array);                                                            // Check whether bound is known to fall within array
+
+  // helper functions to work with predicates
+  Instruction* insert_after(Instruction* insert_position, Instruction* instr, int bci);
+  Instruction* predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1);
+  Instruction* predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=1);
+  Instruction* predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1);
+  Instruction* predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=-1);
+
+  void insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr,      // Add predicate
+                             Instruction *length_instruction, Instruction *lower_instr, int lower,
+                             Instruction *upper_instr, int upper, AccessIndexed *ai);
+  bool is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr,                      // Can we safely add a predicate?
+                                Instruction *length_instr, Instruction *lower_instr,
+                                int lower, Instruction *upper_instr, int upper);
+  void process_if(IntegerStack &pushed, BlockBegin *block, If *cond);                                        // process If Instruction
+  void process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai);                // process indexed access
+
+  void dump_condition_stack(BlockBegin *cur_block);
+  static void print_statistics();
+};
+
+#endif // SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP
--- a/src/share/vm/c1/c1_Runtime1.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1330,6 +1330,50 @@
   return (k != NULL && obj != NULL && obj->is_a(k)) ? 1 : 0;
 JRT_END
 
+JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* thread))
+  ResourceMark rm;
+
+  assert(!TieredCompilation, "incompatible with tiered compilation");
+
+  RegisterMap reg_map(thread, false);
+  frame runtime_frame = thread->last_frame();
+  frame caller_frame = runtime_frame.sender(&reg_map);
+
+  nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
+  assert (nm != NULL, "no more nmethod?");
+  nm->make_not_entrant();
+
+  methodHandle m(nm->method());
+  MethodData* mdo = m->method_data();
+
+  if (mdo == NULL && !HAS_PENDING_EXCEPTION) {
+    // Build an MDO.  Ignore errors like OutOfMemory;
+    // that simply means we won't have an MDO to update.
+    Method::build_interpreter_method_data(m, THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
+      CLEAR_PENDING_EXCEPTION;
+    }
+    mdo = m->method_data();
+  }
+
+  if (mdo != NULL) {
+    mdo->inc_trap_count(Deoptimization::Reason_none);
+  }
+
+  if (TracePredicateFailedTraps) {
+    stringStream ss1, ss2;
+    vframeStream vfst(thread);
+    methodHandle inlinee = methodHandle(vfst.method());
+    inlinee->print_short_name(&ss1);
+    m->print_short_name(&ss2);
+    tty->print_cr("Predicate failed trap in method %s at bci %d inlined in %s at pc %x", ss1.as_string(), vfst.bci(), ss2.as_string(), caller_frame.pc());
+  }
+
+
+  Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_none);
+
+JRT_END
 
 #ifndef PRODUCT
 void Runtime1::print_statistics() {
--- a/src/share/vm/c1/c1_Runtime1.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -71,6 +71,7 @@
   stub(g1_post_barrier_slow)         \
   stub(fpu2long_stub)                \
   stub(counter_overflow)             \
+  stub(predicate_failed_trap)        \
   last_entry(number_of_ids)
 
 #define DECLARE_STUB_ID(x)       x ## _id ,
@@ -190,6 +191,8 @@
   static void oop_arraycopy(HeapWord* src, HeapWord* dst, int length);
   static int  is_instance_of(oopDesc* mirror, oopDesc* obj);
 
+  static void predicate_failed_trap(JavaThread* thread);
+
   static void print_statistics()                 PRODUCT_RETURN;
 };
 
--- a/src/share/vm/c1/c1_ValueMap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_ValueMap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -26,9 +26,9 @@
 #include "c1/c1_Canonicalizer.hpp"
 #include "c1/c1_IR.hpp"
 #include "c1/c1_ValueMap.hpp"
+#include "c1/c1_ValueStack.hpp"
 #include "utilities/bitMap.inline.hpp"
 
-
 #ifndef PRODUCT
 
   int ValueMap::_number_of_finds = 0;
@@ -192,10 +192,6 @@
                    && lf->field()->holder() == field->holder()                           \
                    && (all_offsets || lf->field()->offset() == field->offset());
 
-#define MUST_KILL_EXCEPTION(must_kill, entry, value)                                     \
-  assert(entry->nesting() < nesting(), "must not find bigger nesting than current");     \
-  bool must_kill = (entry->nesting() == nesting() - 1);
-
 
 void ValueMap::kill_memory() {
   GENERIC_KILL_VALUE(MUST_KILL_MEMORY);
@@ -209,11 +205,6 @@
   GENERIC_KILL_VALUE(MUST_KILL_FIELD);
 }
 
-void ValueMap::kill_exception() {
-  GENERIC_KILL_VALUE(MUST_KILL_EXCEPTION);
-}
-
-
 void ValueMap::kill_map(ValueMap* map) {
   assert(is_global_value_numbering(), "only for global value numbering");
   _killed_values.set_union(&map->_killed_values);
@@ -274,6 +265,8 @@
   GlobalValueNumbering* _gvn;
   BlockList             _loop_blocks;
   bool                  _too_complicated_loop;
+  bool                  _has_field_store[T_ARRAY + 1];
+  bool                  _has_indexed_store[T_ARRAY + 1];
 
   // simplified access to methods of GlobalValueNumbering
   ValueMap* current_map()                        { return _gvn->current_map(); }
@@ -281,8 +274,16 @@
 
   // implementation for abstract methods of ValueNumberingVisitor
   void      kill_memory()                                 { _too_complicated_loop = true; }
-  void      kill_field(ciField* field, bool all_offsets)  { current_map()->kill_field(field, all_offsets); };
-  void      kill_array(ValueType* type)                   { current_map()->kill_array(type); };
+  void      kill_field(ciField* field, bool all_offsets)  {
+    current_map()->kill_field(field, all_offsets);
+    assert(field->type()->basic_type() >= 0 && field->type()->basic_type() <= T_ARRAY, "Invalid type");
+    _has_field_store[field->type()->basic_type()] = true;
+  }
+  void      kill_array(ValueType* type)                   {
+    current_map()->kill_array(type);
+    BasicType basic_type = as_BasicType(type); assert(basic_type >= 0 && basic_type <= T_ARRAY, "Invalid type");
+    _has_indexed_store[basic_type] = true;
+  }
 
  public:
   ShortLoopOptimizer(GlobalValueNumbering* gvn)
@@ -290,11 +291,143 @@
     , _loop_blocks(ValueMapMaxLoopSize)
     , _too_complicated_loop(false)
   {
+    for (int i=0; i<= T_ARRAY; i++){
+      _has_field_store[i] = false;
+      _has_indexed_store[i] = false;
+    }
+  }
+
+  bool has_field_store(BasicType type) {
+    assert(type >= 0 && type <= T_ARRAY, "Invalid type");
+    return _has_field_store[type];
+  }
+
+  bool has_indexed_store(BasicType type) {
+    assert(type >= 0 && type <= T_ARRAY, "Invalid type");
+    return _has_indexed_store[type];
   }
 
   bool process(BlockBegin* loop_header);
 };
 
+class LoopInvariantCodeMotion : public StackObj  {
+ private:
+  GlobalValueNumbering* _gvn;
+  ShortLoopOptimizer*   _short_loop_optimizer;
+  Instruction*          _insertion_point;
+  ValueStack *          _state;
+  bool                  _insert_is_pred;
+
+  void set_invariant(Value v) const    { _gvn->set_processed(v); }
+  bool is_invariant(Value v) const     { return _gvn->is_processed(v); }
+
+  void process_block(BlockBegin* block);
+
+ public:
+  LoopInvariantCodeMotion(ShortLoopOptimizer *slo, GlobalValueNumbering* gvn, BlockBegin* loop_header, BlockList* loop_blocks);
+};
+
+LoopInvariantCodeMotion::LoopInvariantCodeMotion(ShortLoopOptimizer *slo, GlobalValueNumbering* gvn, BlockBegin* loop_header, BlockList* loop_blocks)
+  : _gvn(gvn), _short_loop_optimizer(slo) {
+
+  TRACE_VALUE_NUMBERING(tty->print_cr("using loop invariant code motion loop_header = %d", loop_header->block_id()));
+  TRACE_VALUE_NUMBERING(tty->print_cr("** loop invariant code motion for short loop B%d", loop_header->block_id()));
+
+  BlockBegin* insertion_block = loop_header->dominator();
+  if (insertion_block->number_of_preds() == 0) {
+    return;  // only the entry block does not have a predecessor
+  }
+
+  assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block");
+  _insertion_point = insertion_block->end()->prev();
+  _insert_is_pred = loop_header->is_predecessor(insertion_block);
+
+  BlockEnd *block_end = insertion_block->end();
+  _state = block_end->state_before();
+
+  if (!_state) {
+    // If, TableSwitch and LookupSwitch always have state_before when
+    // loop invariant code motion happens..
+    assert(block_end->as_Goto(), "Block has to be goto");
+    _state = block_end->state();
+  }
+
+  // the loop_blocks are filled by going backward from the loop header, so this processing order is best
+  assert(loop_blocks->at(0) == loop_header, "loop header must be first loop block");
+  process_block(loop_header);
+  for (int i = loop_blocks->length() - 1; i >= 1; i--) {
+    process_block(loop_blocks->at(i));
+  }
+}
+
+void LoopInvariantCodeMotion::process_block(BlockBegin* block) {
+  TRACE_VALUE_NUMBERING(tty->print_cr("processing block B%d", block->block_id()));
+
+  Instruction* prev = block;
+  Instruction* cur = block->next();
+
+  while (cur != NULL) {
+
+    // determine if cur instruction is loop invariant
+    // only selected instruction types are processed here
+    bool cur_invariant = false;
+
+    if (cur->as_Constant() != NULL) {
+      cur_invariant = !cur->can_trap();
+    } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) {
+      assert(cur->as_Op2() != NULL, "must be Op2");
+      Op2* op2 = (Op2*)cur;
+      cur_invariant = !op2->can_trap() && is_invariant(op2->x()) && is_invariant(op2->y());
+    } else if (cur->as_LoadField() != NULL) {
+      LoadField* lf = (LoadField*)cur;
+      // deoptimizes on NullPointerException
+      cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred;
+    } else if (cur->as_ArrayLength() != NULL) {
+      ArrayLength *length = cur->as_ArrayLength();
+      cur_invariant = is_invariant(length->array());
+    } else if (cur->as_LoadIndexed() != NULL) {
+      LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed();
+      cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred;
+    }
+
+    if (cur_invariant) {
+      // perform value numbering and mark instruction as loop-invariant
+      _gvn->substitute(cur);
+
+      if (cur->as_Constant() == NULL) {
+        // ensure that code for non-constant instructions is always generated
+        cur->pin();
+      }
+
+      // remove cur instruction from loop block and append it to block before loop
+      Instruction* next = cur->next();
+      Instruction* in = _insertion_point->next();
+      _insertion_point = _insertion_point->set_next(cur);
+      cur->set_next(in);
+
+      //  Deoptimize on exception
+      cur->set_flag(Instruction::DeoptimizeOnException, true);
+
+      //  Clear exception handlers
+      cur->set_exception_handlers(NULL);
+
+      TRACE_VALUE_NUMBERING(tty->print_cr("Instruction %c%d is loop invariant", cur->type()->tchar(), cur->id()));
+
+      if (cur->state_before() != NULL) {
+        cur->set_state_before(_state->copy());
+      }
+      if (cur->exception_state() != NULL) {
+        cur->set_exception_state(_state->copy());
+      }
+
+      cur = prev->set_next(next);
+
+    } else {
+      prev = cur;
+      cur = cur->next();
+    }
+  }
+}
 
 bool ShortLoopOptimizer::process(BlockBegin* loop_header) {
   TRACE_VALUE_NUMBERING(tty->print_cr("** loop header block"));
@@ -316,6 +449,10 @@
     for (int j = block->number_of_preds() - 1; j >= 0; j--) {
       BlockBegin* pred = block->pred_at(j);
 
+      if (pred->is_set(BlockBegin::osr_entry_flag)) {
+        return false;
+      }
+
       ValueMap* pred_map = value_map_of(pred);
       if (pred_map != NULL) {
         current_map()->kill_map(pred_map);
@@ -336,6 +473,12 @@
     }
   }
 
+  bool optimistic = this->_gvn->compilation()->is_optimistic();
+
+  if (UseLoopInvariantCodeMotion && optimistic) {
+    LoopInvariantCodeMotion code_motion(this, _gvn, loop_header, &_loop_blocks);
+  }
+
   TRACE_VALUE_NUMBERING(tty->print_cr("** loop successfully optimized"));
   return true;
 }
@@ -344,11 +487,11 @@
 GlobalValueNumbering::GlobalValueNumbering(IR* ir)
   : _current_map(NULL)
   , _value_maps(ir->linear_scan_order()->length(), NULL)
+  , _compilation(ir->compilation())
 {
   TRACE_VALUE_NUMBERING(tty->print_cr("****** start of global value numbering"));
 
   ShortLoopOptimizer short_loop_optimizer(this);
-  int subst_count = 0;
 
   BlockList* blocks = ir->linear_scan_order();
   int num_blocks = blocks->length();
@@ -357,6 +500,12 @@
   assert(start_block == ir->start() && start_block->number_of_preds() == 0 && start_block->dominator() == NULL, "must be start block");
   assert(start_block->next()->as_Base() != NULL && start_block->next()->next() == NULL, "start block must not have instructions");
 
+  // method parameters are not linked in instructions list, so process them separateley
+  for_each_state_value(start_block->state(), value,
+     assert(value->as_Local() != NULL, "only method parameters allowed");
+     set_processed(value);
+  );
+
   // initial, empty value map with nesting 0
   set_value_map_of(start_block, new ValueMap());
 
@@ -374,7 +523,7 @@
     // create new value map with increased nesting
     _current_map = new ValueMap(value_map_of(dominator));
 
-    if (num_preds == 1) {
+    if (num_preds == 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
       assert(dominator == block->pred_at(0), "dominator must be equal to predecessor");
       // nothing to do here
 
@@ -403,36 +552,41 @@
       }
     }
 
-    if (block->is_set(BlockBegin::exception_entry_flag)) {
-      current_map()->kill_exception();
-    }
+    // phi functions are not linked in instructions list, so process them separateley
+    for_each_phi_fun(block, phi,
+      set_processed(phi);
+    );
 
     TRACE_VALUE_NUMBERING(tty->print("value map before processing block: "); current_map()->print());
 
     // visit all instructions of this block
     for (Value instr = block->next(); instr != NULL; instr = instr->next()) {
-      assert(!instr->has_subst(), "substitution already set");
-
       // check if instruction kills any values
       instr->visit(this);
-
-      if (instr->hash() != 0) {
-        Value f = current_map()->find_insert(instr);
-        if (f != instr) {
-          assert(!f->has_subst(), "can't have a substitution");
-          instr->set_subst(f);
-          subst_count++;
-        }
-      }
+      // perform actual value numbering
+      substitute(instr);
     }
 
     // remember value map for successors
     set_value_map_of(block, current_map());
   }
 
-  if (subst_count != 0) {
+  if (_has_substitutions) {
     SubstitutionResolver resolver(ir);
   }
 
   TRACE_VALUE_NUMBERING(tty->print("****** end of global value numbering. "); ValueMap::print_statistics());
 }
+
+void GlobalValueNumbering::substitute(Instruction* instr) {
+  assert(!instr->has_subst(), "substitution already set");
+  Value subst = current_map()->find_insert(instr);
+  if (subst != instr) {
+    assert(!subst->has_subst(), "can't have a substitution");
+
+    TRACE_VALUE_NUMBERING(tty->print_cr("substitution for %d set to %d", instr->id(), subst->id()));
+    instr->set_subst(subst);
+    _has_substitutions = true;
+  }
+  set_processed(instr);
+}
--- a/src/share/vm/c1/c1_ValueMap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_ValueMap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -206,6 +206,8 @@
   void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
   void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
   void do_MemBar         (MemBar*          x) { /* nothing to do */ };
+  void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ };
+  void do_Assert         (Assert*          x) { /* nothing to do */ };
 };
 
 
@@ -225,15 +227,22 @@
 
 class GlobalValueNumbering: public ValueNumberingVisitor {
  private:
+  Compilation*  _compilation;     // compilation data
   ValueMap*     _current_map;     // value map of current block
   ValueMapArray _value_maps;      // list of value maps for all blocks
+  ValueSet      _processed_values;  // marker for instructions that were already processed
+  bool          _has_substitutions; // set to true when substitutions must be resolved
 
  public:
   // accessors
+  Compilation*  compilation() const              { return _compilation; }
   ValueMap*     current_map()                    { return _current_map; }
   ValueMap*     value_map_of(BlockBegin* block)  { return _value_maps.at(block->linear_scan_number()); }
   void          set_value_map_of(BlockBegin* block, ValueMap* map)   { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); }
 
+  bool          is_processed(Value v)            { return _processed_values.contains(v); }
+  void          set_processed(Value v)           { _processed_values.put(v); }
+
   // implementation for abstract methods of ValueNumberingVisitor
   void          kill_memory()                                 { current_map()->kill_memory(); }
   void          kill_field(ciField* field, bool all_offsets)  { current_map()->kill_field(field, all_offsets); }
@@ -241,6 +250,7 @@
 
   // main entry point that performs global value numbering
   GlobalValueNumbering(IR* ir);
+  void          substitute(Instruction* instr);  // substitute instruction if it is contained in current value map
 };
 
 #endif // SHARE_VM_C1_C1_VALUEMAP_HPP
--- a/src/share/vm/c1/c1_globals.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/c1/c1_globals.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -119,6 +119,24 @@
   develop(bool, UseGlobalValueNumbering, true,                              \
           "Use Global Value Numbering (separate phase)")                    \
                                                                             \
+  product(bool, UseLoopInvariantCodeMotion, true,                           \
+          "Simple loop invariant code motion for short loops during GVN")   \
+                                                                            \
+  develop(bool, TracePredicateFailedTraps, false,                           \
+          "trace runtime traps caused by predicate failure")                \
+                                                                            \
+  develop(bool, StressLoopInvariantCodeMotion, false,                       \
+          "stress loop invariant code motion")                              \
+                                                                            \
+  develop(bool, TraceRangeCheckElimination, false,                          \
+          "Trace Range Check Elimination")                                  \
+                                                                            \
+  develop(bool, AssertRangeCheckElimination, false,                         \
+          "Assert Range Check Elimination")                                 \
+                                                                            \
+  develop(bool, StressRangeCheckElimination, false,                         \
+          "stress Range Check Elimination")                                 \
+                                                                            \
   develop(bool, PrintValueNumbering, false,                                 \
           "Print Value Numbering")                                          \
                                                                             \
--- a/src/share/vm/ci/ciEnv.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/ci/ciEnv.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -802,6 +802,7 @@
   // require checks to make sure the expected type was found.  Given that this
   // only occurs for clone() the more extensive fix seems like overkill so
   // instead we simply smear the array type into Object.
+  guarantee(method_holder != NULL, "no method holder");
   if (method_holder->is_instance_klass()) {
     return method_holder->as_instance_klass();
   } else if (method_holder->is_array_klass()) {
--- a/src/share/vm/ci/ciMethod.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/ci/ciMethod.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -790,6 +790,17 @@
   return count;
 }
 
+
+// ------------------------------------------------------------------
+// ciMethod::is_special_get_caller_class_method
+//
+bool ciMethod::is_ignored_by_security_stack_walk() const {
+  check_is_loaded();
+  VM_ENTRY_MARK;
+  return get_Method()->is_ignored_by_security_stack_walk();
+}
+
+
 // ------------------------------------------------------------------
 // invokedynamic support
 
--- a/src/share/vm/ci/ciMethod.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/ci/ciMethod.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -166,8 +166,9 @@
   // Code size for inlining decisions.
   int code_size_for_inlining();
 
-  bool force_inline() { return get_Method()->force_inline(); }
-  bool dont_inline()  { return get_Method()->dont_inline();  }
+  bool caller_sensitive() { return get_Method()->caller_sensitive(); }
+  bool force_inline()     { return get_Method()->force_inline();     }
+  bool dont_inline()      { return get_Method()->dont_inline();      }
 
   int comp_level();
   int highest_osr_comp_level();
@@ -264,6 +265,9 @@
   int instructions_size();
   int scale_count(int count, float prof_factor = 1.);  // make MDO count commensurate with IIC
 
+  // Stack walking support
+  bool is_ignored_by_security_stack_walk() const;
+
   // JSR 292 support
   bool is_method_handle_intrinsic()  const;
   bool is_compiled_lambda_form() const;
--- a/src/share/vm/ci/ciTypeFlow.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -2540,7 +2540,7 @@
   } else if (innermost->head() == blk) {
     // If loop header, complete the tree pointers
     if (blk->loop() != innermost) {
-#if ASSERT
+#ifdef ASSERT
       assert(blk->loop()->head() == innermost->head(), "same head");
       Loop* dl;
       for (dl = innermost; dl != NULL && dl != blk->loop(); dl = dl->parent());
--- a/src/share/vm/classfile/classFileParser.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/classFileParser.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -90,8 +90,7 @@
 // Extension method support.
 #define JAVA_8_VERSION                    52
 
-
-void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
+void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {
   // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
   // this function (_current can be allocated in a register, with scalar
   // replacement of aggregates). The _current pointer is copied back to
@@ -104,7 +103,7 @@
   assert(cfs->allocated_on_stack(),"should be local");
   u1* old_current = cfs0->current();
 #endif
-  Handle class_loader(THREAD, loader_data->class_loader());
+  Handle class_loader(THREAD, _loader_data->class_loader());
 
   // Used for batching symbol allocations.
   const char* names[SymbolTable::symbol_alloc_batch_size];
@@ -124,7 +123,7 @@
         {
           cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
           u2 name_index = cfs->get_u2_fast();
-          cp->klass_index_at_put(index, name_index);
+          _cp->klass_index_at_put(index, name_index);
         }
         break;
       case JVM_CONSTANT_Fieldref :
@@ -132,7 +131,7 @@
           cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
           u2 class_index = cfs->get_u2_fast();
           u2 name_and_type_index = cfs->get_u2_fast();
-          cp->field_at_put(index, class_index, name_and_type_index);
+          _cp->field_at_put(index, class_index, name_and_type_index);
         }
         break;
       case JVM_CONSTANT_Methodref :
@@ -140,7 +139,7 @@
           cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
           u2 class_index = cfs->get_u2_fast();
           u2 name_and_type_index = cfs->get_u2_fast();
-          cp->method_at_put(index, class_index, name_and_type_index);
+          _cp->method_at_put(index, class_index, name_and_type_index);
         }
         break;
       case JVM_CONSTANT_InterfaceMethodref :
@@ -148,14 +147,14 @@
           cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
           u2 class_index = cfs->get_u2_fast();
           u2 name_and_type_index = cfs->get_u2_fast();
-          cp->interface_method_at_put(index, class_index, name_and_type_index);
+          _cp->interface_method_at_put(index, class_index, name_and_type_index);
         }
         break;
       case JVM_CONSTANT_String :
         {
           cfs->guarantee_more(3, CHECK);  // string_index, tag/access_flags
           u2 string_index = cfs->get_u2_fast();
-          cp->string_index_at_put(index, string_index);
+          _cp->string_index_at_put(index, string_index);
         }
         break;
       case JVM_CONSTANT_MethodHandle :
@@ -174,11 +173,11 @@
           cfs->guarantee_more(4, CHECK);  // ref_kind, method_index, tag/access_flags
           u1 ref_kind = cfs->get_u1_fast();
           u2 method_index = cfs->get_u2_fast();
-          cp->method_handle_index_at_put(index, ref_kind, method_index);
+          _cp->method_handle_index_at_put(index, ref_kind, method_index);
         } else if (tag == JVM_CONSTANT_MethodType) {
           cfs->guarantee_more(3, CHECK);  // signature_index, tag/access_flags
           u2 signature_index = cfs->get_u2_fast();
-          cp->method_type_index_at_put(index, signature_index);
+          _cp->method_type_index_at_put(index, signature_index);
         } else {
           ShouldNotReachHere();
         }
@@ -200,21 +199,21 @@
           u2 name_and_type_index = cfs->get_u2_fast();
           if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
             _max_bootstrap_specifier_index = (int) bootstrap_specifier_index;  // collect for later
-          cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
+          _cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
         }
         break;
       case JVM_CONSTANT_Integer :
         {
           cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags
           u4 bytes = cfs->get_u4_fast();
-          cp->int_at_put(index, (jint) bytes);
+          _cp->int_at_put(index, (jint) bytes);
         }
         break;
       case JVM_CONSTANT_Float :
         {
           cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags
           u4 bytes = cfs->get_u4_fast();
-          cp->float_at_put(index, *(jfloat*)&bytes);
+          _cp->float_at_put(index, *(jfloat*)&bytes);
         }
         break;
       case JVM_CONSTANT_Long :
@@ -225,7 +224,7 @@
         {
           cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
           u8 bytes = cfs->get_u8_fast();
-          cp->long_at_put(index, bytes);
+          _cp->long_at_put(index, bytes);
         }
         index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
         break;
@@ -237,7 +236,7 @@
         {
           cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
           u8 bytes = cfs->get_u8_fast();
-          cp->double_at_put(index, *(jdouble*)&bytes);
+          _cp->double_at_put(index, *(jdouble*)&bytes);
         }
         index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
         break;
@@ -246,7 +245,7 @@
           cfs->guarantee_more(5, CHECK);  // name_index, signature_index, tag/access_flags
           u2 name_index = cfs->get_u2_fast();
           u2 signature_index = cfs->get_u2_fast();
-          cp->name_and_type_at_put(index, name_index, signature_index);
+          _cp->name_and_type_at_put(index, name_index, signature_index);
         }
         break;
       case JVM_CONSTANT_Utf8 :
@@ -283,11 +282,11 @@
             indices[names_count] = index;
             hashValues[names_count++] = hash;
             if (names_count == SymbolTable::symbol_alloc_batch_size) {
-              SymbolTable::new_symbols(loader_data, cp, names_count, names, lengths, indices, hashValues, CHECK);
+              SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
               names_count = 0;
             }
           } else {
-            cp->symbol_at_put(index, result);
+            _cp->symbol_at_put(index, result);
           }
         }
         break;
@@ -300,7 +299,7 @@
 
   // Allocate the remaining symbols
   if (names_count > 0) {
-    SymbolTable::new_symbols(loader_data, cp, names_count, names, lengths, indices, hashValues, CHECK);
+    SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
   }
 
   // Copy _current pointer of local copy back to stream().
@@ -310,23 +309,6 @@
   cfs0->set_current(cfs1.current());
 }
 
-// This class unreferences constant pool symbols if an error has occurred
-// while parsing the class before it is assigned into the class.
-// If it gets an error after that it is unloaded and the constant pool will
-// be cleaned up then.
-class ConstantPoolCleaner : public StackObj {
-  constantPoolHandle _cphandle;
-  bool               _in_error;
- public:
-  ConstantPoolCleaner(constantPoolHandle cp) : _cphandle(cp), _in_error(true) {}
-  ~ConstantPoolCleaner() {
-    if (_in_error && _cphandle.not_null()) {
-      _cphandle->unreference_symbols();
-    }
-  }
-  void set_in_error(bool clean) { _in_error = clean; }
-};
-
 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
 
 inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
@@ -336,7 +318,7 @@
     return NULL;
 }
 
-constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_data, TRAPS) {
+constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
   ClassFileStream* cfs = stream();
   constantPoolHandle nullHandle;
 
@@ -345,16 +327,13 @@
   guarantee_property(
     length >= 1, "Illegal constant pool size %u in class file %s",
     length, CHECK_(nullHandle));
-  ConstantPool* constant_pool =
-                      ConstantPool::allocate(loader_data,
-                                                    length,
-                                                   CHECK_(nullHandle));
+  ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
+                                                        CHECK_(nullHandle));
+  _cp = constant_pool; // save in case of errors
   constantPoolHandle cp (THREAD, constant_pool);
 
-  ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
-
   // parsing constant pool entries
-  parse_constant_pool_entries(loader_data, cp, length, CHECK_(nullHandle));
+  parse_constant_pool_entries(length, CHECK_(nullHandle));
 
   int index = 1;  // declared outside of loops for portability
 
@@ -373,8 +352,7 @@
         if (!_need_verify) break;
         int klass_ref_index = cp->klass_ref_index_at(index);
         int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
-        check_property(valid_cp_range(klass_ref_index, length) &&
-                       is_klass_reference(cp, klass_ref_index),
+        check_property(valid_klass_reference_at(klass_ref_index),
                        "Invalid constant pool index %u in class file %s",
                        klass_ref_index,
                        CHECK_(nullHandle));
@@ -404,16 +382,12 @@
         if (!_need_verify) break;
         int name_ref_index = cp->name_ref_index_at(index);
         int signature_ref_index = cp->signature_ref_index_at(index);
-        check_property(
-          valid_cp_range(name_ref_index, length) &&
-            cp->tag_at(name_ref_index).is_utf8(),
-          "Invalid constant pool index %u in class file %s",
-          name_ref_index, CHECK_(nullHandle));
-        check_property(
-          valid_cp_range(signature_ref_index, length) &&
-            cp->tag_at(signature_ref_index).is_utf8(),
-          "Invalid constant pool index %u in class file %s",
-          signature_ref_index, CHECK_(nullHandle));
+        check_property(valid_symbol_at(name_ref_index),
+                 "Invalid constant pool index %u in class file %s",
+                 name_ref_index, CHECK_(nullHandle));
+        check_property(valid_symbol_at(signature_ref_index),
+                 "Invalid constant pool index %u in class file %s",
+                 signature_ref_index, CHECK_(nullHandle));
         break;
       }
       case JVM_CONSTANT_Utf8 :
@@ -425,22 +399,18 @@
       case JVM_CONSTANT_ClassIndex :
         {
           int class_index = cp->klass_index_at(index);
-          check_property(
-            valid_cp_range(class_index, length) &&
-              cp->tag_at(class_index).is_utf8(),
-            "Invalid constant pool index %u in class file %s",
-            class_index, CHECK_(nullHandle));
+          check_property(valid_symbol_at(class_index),
+                 "Invalid constant pool index %u in class file %s",
+                 class_index, CHECK_(nullHandle));
           cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
         }
         break;
       case JVM_CONSTANT_StringIndex :
         {
           int string_index = cp->string_index_at(index);
-          check_property(
-            valid_cp_range(string_index, length) &&
-              cp->tag_at(string_index).is_utf8(),
-            "Invalid constant pool index %u in class file %s",
-            string_index, CHECK_(nullHandle));
+          check_property(valid_symbol_at(string_index),
+                 "Invalid constant pool index %u in class file %s",
+                 string_index, CHECK_(nullHandle));
           Symbol* sym = cp->symbol_at(string_index);
           cp->unresolved_string_at_put(index, sym);
         }
@@ -491,12 +461,9 @@
       case JVM_CONSTANT_MethodType :
         {
           int ref_index = cp->method_type_index_at(index);
-          check_property(
-            valid_cp_range(ref_index, length) &&
-                cp->tag_at(ref_index).is_utf8() &&
-                EnableInvokeDynamic,
-              "Invalid constant pool index %u in class file %s",
-              ref_index, CHECK_(nullHandle));
+          check_property(valid_symbol_at(ref_index) && EnableInvokeDynamic,
+                 "Invalid constant pool index %u in class file %s",
+                 ref_index, CHECK_(nullHandle));
         }
         break;
       case JVM_CONSTANT_InvokeDynamic :
@@ -541,7 +508,6 @@
   }
 
   if (!_need_verify) {
-    cp_in_error.set_in_error(false);
     return cp;
   }
 
@@ -664,7 +630,6 @@
     }  // end of switch
   }  // end of for
 
-  cp_in_error.set_in_error(false);
   return cp;
 }
 
@@ -786,93 +751,92 @@
 }
 
 
-Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
-                                                 int length,
-                                                 ClassLoaderData* loader_data,
+Array<Klass*>* ClassFileParser::parse_interfaces(int length,
                                                  Handle protection_domain,
                                                  Symbol* class_name,
                                                  bool* has_default_methods,
                                                  TRAPS) {
-  ClassFileStream* cfs = stream();
-  assert(length > 0, "only called for length>0");
-  // FIXME: Leak at later OOM.
-  Array<Klass*>* interfaces = MetadataFactory::new_array<Klass*>(loader_data, length, NULL, CHECK_NULL);
-
-  int index;
-  for (index = 0; index < length; index++) {
-    u2 interface_index = cfs->get_u2(CHECK_NULL);
-    KlassHandle interf;
-    check_property(
-      valid_cp_range(interface_index, cp->length()) &&
-      is_klass_reference(cp, interface_index),
-      "Interface name has bad constant pool index %u in class file %s",
-      interface_index, CHECK_NULL);
-    if (cp->tag_at(interface_index).is_klass()) {
-      interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));
-    } else {
-      Symbol*  unresolved_klass  = cp->klass_name_at(interface_index);
-
-      // Don't need to check legal name because it's checked when parsing constant pool.
-      // But need to make sure it's not an array type.
-      guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
-                         "Bad interface name in class file %s", CHECK_NULL);
-      Handle class_loader(THREAD, loader_data->class_loader());
-
-      // Call resolve_super so classcircularity is checked
-      Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
-                    unresolved_klass, class_loader, protection_domain,
-                    false, CHECK_NULL);
-      interf = KlassHandle(THREAD, k);
+  if (length == 0) {
+    _local_interfaces = Universe::the_empty_klass_array();
+  } else {
+    ClassFileStream* cfs = stream();
+    assert(length > 0, "only called for length>0");
+    _local_interfaces = MetadataFactory::new_array<Klass*>(_loader_data, length, NULL, CHECK_NULL);
+
+    int index;
+    for (index = 0; index < length; index++) {
+      u2 interface_index = cfs->get_u2(CHECK_NULL);
+      KlassHandle interf;
+      check_property(
+        valid_klass_reference_at(interface_index),
+        "Interface name has bad constant pool index %u in class file %s",
+        interface_index, CHECK_NULL);
+      if (_cp->tag_at(interface_index).is_klass()) {
+        interf = KlassHandle(THREAD, _cp->resolved_klass_at(interface_index));
+      } else {
+        Symbol*  unresolved_klass  = _cp->klass_name_at(interface_index);
+
+        // Don't need to check legal name because it's checked when parsing constant pool.
+        // But need to make sure it's not an array type.
+        guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
+                           "Bad interface name in class file %s", CHECK_NULL);
+        Handle class_loader(THREAD, _loader_data->class_loader());
+
+        // Call resolve_super so classcircularity is checked
+        Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
+                      unresolved_klass, class_loader, protection_domain,
+                      false, CHECK_NULL);
+        interf = KlassHandle(THREAD, k);
+      }
+
+      if (!interf()->is_interface()) {
+        THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
+      }
+      if (InstanceKlass::cast(interf())->has_default_methods()) {
+        *has_default_methods = true;
+      }
+      _local_interfaces->at_put(index, interf());
     }
 
-    if (!interf()->is_interface()) {
-      THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
-    }
-    if (InstanceKlass::cast(interf())->has_default_methods()) {
-      *has_default_methods = true;
+    if (!_need_verify || length <= 1) {
+      return _local_interfaces;
     }
-    interfaces->at_put(index, interf());
-  }
-
-  if (!_need_verify || length <= 1) {
-    return interfaces;
-  }
-
-  // Check if there's any duplicates in interfaces
-  ResourceMark rm(THREAD);
-  NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(
-    THREAD, NameSigHash*, HASH_ROW_SIZE);
-  initialize_hashtable(interface_names);
-  bool dup = false;
-  {
-    debug_only(No_Safepoint_Verifier nsv;)
-    for (index = 0; index < length; index++) {
-      Klass* k = interfaces->at(index);
-      Symbol* name = InstanceKlass::cast(k)->name();
-      // If no duplicates, add (name, NULL) in hashtable interface_names.
-      if (!put_after_lookup(name, NULL, interface_names)) {
-        dup = true;
-        break;
+
+    // Check if there's any duplicates in interfaces
+    ResourceMark rm(THREAD);
+    NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(
+      THREAD, NameSigHash*, HASH_ROW_SIZE);
+    initialize_hashtable(interface_names);
+    bool dup = false;
+    {
+      debug_only(No_Safepoint_Verifier nsv;)
+      for (index = 0; index < length; index++) {
+        Klass* k = _local_interfaces->at(index);
+        Symbol* name = InstanceKlass::cast(k)->name();
+        // If no duplicates, add (name, NULL) in hashtable interface_names.
+        if (!put_after_lookup(name, NULL, interface_names)) {
+          dup = true;
+          break;
+        }
       }
     }
-  }
-  if (dup) {
-    classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
+    if (dup) {
+      classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
+    }
   }
-
-  return interfaces;
+  return _local_interfaces;
 }
 
 
-void ClassFileParser::verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS) {
+void ClassFileParser::verify_constantvalue(int constantvalue_index, int signature_index, TRAPS) {
   // Make sure the constant pool entry is of a type appropriate to this field
   guarantee_property(
     (constantvalue_index > 0 &&
-      constantvalue_index < cp->length()),
+      constantvalue_index < _cp->length()),
     "Bad initial value index %u in ConstantValue attribute in class file %s",
     constantvalue_index, CHECK);
-  constantTag value_type = cp->tag_at(constantvalue_index);
-  switch ( cp->basic_type_for_signature_at(signature_index) ) {
+  constantTag value_type = _cp->tag_at(constantvalue_index);
+  switch ( _cp->basic_type_for_signature_at(signature_index) ) {
     case T_LONG:
       guarantee_property(value_type.is_long(), "Inconsistent constant value type in class file %s", CHECK);
       break;
@@ -886,7 +850,7 @@
       guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
       break;
     case T_OBJECT:
-      guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
+      guarantee_property((_cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
                          && value_type.is_string()),
                          "Bad string initial value in class file %s", CHECK);
       break;
@@ -899,15 +863,11 @@
 
 
 // Parse attributes for a field.
-void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
-                                             constantPoolHandle cp,
-                                             u2 attributes_count,
+void ClassFileParser::parse_field_attributes(u2 attributes_count,
                                              bool is_static, u2 signature_index,
                                              u2* constantvalue_index_addr,
                                              bool* is_synthetic_addr,
                                              u2* generic_signature_index_addr,
-                                             AnnotationArray** field_annotations,
-                                             AnnotationArray** field_type_annotations,
                                              ClassFileParser::FieldAnnotationCollector* parsed_annotations,
                                              TRAPS) {
   ClassFileStream* cfs = stream();
@@ -927,12 +887,11 @@
     cfs->guarantee_more(6, CHECK);  // attribute_name_index, attribute_length
     u2 attribute_name_index = cfs->get_u2_fast();
     u4 attribute_length = cfs->get_u4_fast();
-    check_property(valid_cp_range(attribute_name_index, cp->length()) &&
-                   cp->tag_at(attribute_name_index).is_utf8(),
+    check_property(valid_symbol_at(attribute_name_index),
                    "Invalid field attribute index %u in class file %s",
                    attribute_name_index,
                    CHECK);
-    Symbol* attribute_name = cp->symbol_at(attribute_name_index);
+    Symbol* attribute_name = _cp->symbol_at(attribute_name_index);
     if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
       // ignore if non-static
       if (constantvalue_index != 0) {
@@ -944,7 +903,7 @@
         attribute_length, CHECK);
       constantvalue_index = cfs->get_u2(CHECK);
       if (_need_verify) {
-        verify_constantvalue(constantvalue_index, signature_index, cp, CHECK);
+        verify_constantvalue(constantvalue_index, signature_index, CHECK);
       }
     } else if (attribute_name == vmSymbols::tag_synthetic()) {
       if (attribute_length != 0) {
@@ -971,10 +930,8 @@
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
-        parse_annotations(loader_data,
-                          runtime_visible_annotations,
+        parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
-                          cp,
                           parsed_annotations,
                           CHECK);
         cfs->skip_u1(runtime_visible_annotations_length, CHECK);
@@ -1004,18 +961,18 @@
   *constantvalue_index_addr = constantvalue_index;
   *is_synthetic_addr = is_synthetic;
   *generic_signature_index_addr = generic_signature_index;
-  *field_annotations = assemble_annotations(loader_data,
-                                            runtime_visible_annotations,
+  AnnotationArray* a = assemble_annotations(runtime_visible_annotations,
                                             runtime_visible_annotations_length,
                                             runtime_invisible_annotations,
                                             runtime_invisible_annotations_length,
                                             CHECK);
-  *field_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);
+  parsed_annotations->set_field_annotations(a);
+  a = assemble_annotations(runtime_visible_type_annotations,
+                           runtime_visible_type_annotations_length,
+                           runtime_invisible_type_annotations,
+                           runtime_invisible_type_annotations_length,
+                           CHECK);
+  parsed_annotations->set_field_type_annotations(a);
   return;
 }
 
@@ -1106,13 +1063,9 @@
   }
 };
 
-Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
-                                         Symbol* class_name,
-                                         constantPoolHandle cp,
+Array<u2>* ClassFileParser::parse_fields(Symbol* class_name,
                                          bool is_interface,
                                          FieldAllocationCount *fac,
-                                         Array<AnnotationArray*>** fields_annotations,
-                                         Array<AnnotationArray*>** fields_type_annotations,
                                          u2* java_fields_count_ptr, TRAPS) {
   ClassFileStream* cfs = stream();
   cfs->guarantee_more(2, CHECK_NULL);  // length
@@ -1147,8 +1100,6 @@
   u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD(
              THREAD, u2, total_fields * (FieldInfo::field_slots + 1));
 
-  AnnotationArray* field_annotations = NULL;
-  AnnotationArray* field_type_annotations = NULL;
   // The generic signature slots start after all other fields' data.
   int generic_signature_slot = total_fields * FieldInfo::field_slots;
   int num_generic_signature = 0;
@@ -1161,53 +1112,52 @@
     access_flags.set_flags(flags);
 
     u2 name_index = cfs->get_u2_fast();
-    int cp_size = cp->length();
-    check_property(
-      valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(),
+    int cp_size = _cp->length();
+    check_property(valid_symbol_at(name_index),
       "Invalid constant pool index %u for field name in class file %s",
-      name_index, CHECK_NULL);
-    Symbol*  name = cp->symbol_at(name_index);
+      name_index,
+      CHECK_NULL);
+    Symbol*  name = _cp->symbol_at(name_index);
     verify_legal_field_name(name, CHECK_NULL);
 
     u2 signature_index = cfs->get_u2_fast();
-    check_property(
-      valid_cp_range(signature_index, cp_size) &&
-        cp->tag_at(signature_index).is_utf8(),
+    check_property(valid_symbol_at(signature_index),
       "Invalid constant pool index %u for field signature in class file %s",
       signature_index, CHECK_NULL);
-    Symbol*  sig = cp->symbol_at(signature_index);
+    Symbol*  sig = _cp->symbol_at(signature_index);
     verify_legal_field_signature(name, sig, CHECK_NULL);
 
     u2 constantvalue_index = 0;
     bool is_synthetic = false;
     u2 generic_signature_index = 0;
     bool is_static = access_flags.is_static();
-    FieldAnnotationCollector parsed_annotations;
+    FieldAnnotationCollector parsed_annotations(_loader_data);
 
     u2 attributes_count = cfs->get_u2_fast();
     if (attributes_count > 0) {
-      parse_field_attributes(loader_data,
-                             cp, attributes_count, is_static, signature_index,
+      parse_field_attributes(attributes_count, is_static, signature_index,
                              &constantvalue_index, &is_synthetic,
-                             &generic_signature_index, &field_annotations,
-                             &field_type_annotations, &parsed_annotations,
+                             &generic_signature_index, &parsed_annotations,
                              CHECK_NULL);
-      if (field_annotations != NULL) {
-        if (*fields_annotations == NULL) {
-          *fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
-                                             loader_data, length, NULL,
+      if (parsed_annotations.field_annotations() != NULL) {
+        if (_fields_annotations == NULL) {
+          _fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
+                                             _loader_data, length, NULL,
                                              CHECK_NULL);
         }
-        (*fields_annotations)->at_put(n, field_annotations);
+        _fields_annotations->at_put(n, parsed_annotations.field_annotations());
+        parsed_annotations.set_field_annotations(NULL);
       }
-      if (field_type_annotations != NULL) {
-        if (*fields_type_annotations == NULL) {
-          *fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
-                                                  loader_data, length, NULL,
+      if (parsed_annotations.field_type_annotations() != NULL) {
+        if (_fields_type_annotations == NULL) {
+          _fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
+                                                  _loader_data, length, NULL,
                                                   CHECK_NULL);
         }
-        (*fields_type_annotations)->at_put(n, field_type_annotations);
+        _fields_type_annotations->at_put(n, parsed_annotations.field_type_annotations());
+        parsed_annotations.set_field_type_annotations(NULL);
       }
+
       if (is_synthetic) {
         access_flags.set_is_synthetic();
       }
@@ -1224,7 +1174,7 @@
                       name_index,
                       signature_index,
                       constantvalue_index);
-    BasicType type = cp->basic_type_for_signature_at(signature_index);
+    BasicType type = _cp->basic_type_for_signature_at(signature_index);
 
     // Remember how many oops we encountered and compute allocation type
     FieldAllocationType atype = fac->update(is_static, type);
@@ -1245,8 +1195,8 @@
         bool duplicate = false;
         for (int i = 0; i < length; i++) {
           FieldInfo* f = FieldInfo::from_field_array(fa, i);
-          if (name      == cp->symbol_at(f->name_index()) &&
-              signature == cp->symbol_at(f->signature_index())) {
+          if (name      == _cp->symbol_at(f->name_index()) &&
+              signature == _cp->symbol_at(f->signature_index())) {
             // Symbol is desclared in Java so skip this one
             duplicate = true;
             break;
@@ -1280,8 +1230,9 @@
   // fields array is trimed. Also unused slots that were reserved
   // for generic signature indexes are discarded.
   Array<u2>* fields = MetadataFactory::new_array<u2>(
-          loader_data, index * FieldInfo::field_slots + num_generic_signature,
+          _loader_data, index * FieldInfo::field_slots + num_generic_signature,
           CHECK_NULL);
+  _fields = fields; // save in case of error
   {
     int i = 0;
     for (; i < index * FieldInfo::field_slots; i++) {
@@ -1303,7 +1254,7 @@
     bool dup = false;
     {
       debug_only(No_Safepoint_Verifier nsv;)
-      for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
+      for (AllFieldStream fs(fields, _cp); !fs.done(); fs.next()) {
         Symbol* name = fs.name();
         Symbol* sig = fs.signature();
         // If no duplicates, add name/signature in hashtable names_and_sigs.
@@ -1330,10 +1281,8 @@
 }
 
 
-u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data,
-                                           u4 code_length,
+u2* ClassFileParser::parse_exception_table(u4 code_length,
                                            u4 exception_table_length,
-                                           constantPoolHandle cp,
                                            TRAPS) {
   ClassFileStream* cfs = stream();
 
@@ -1354,8 +1303,7 @@
                          "Illegal exception table handler in class file %s",
                          CHECK_NULL);
       if (catch_type_index != 0) {
-        guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
-                           is_klass_reference(cp, catch_type_index),
+        guarantee_property(valid_klass_reference_at(catch_type_index),
                            "Catch type in exception table has bad constant type in class file %s", CHECK_NULL);
       }
     }
@@ -1506,7 +1454,6 @@
 u2* ClassFileParser::parse_localvariable_table(u4 code_length,
                                                u2 max_locals,
                                                u4 code_attribute_length,
-                                               constantPoolHandle cp,
                                                u2* localvariable_table_length,
                                                bool isLVTT,
                                                TRAPS) {
@@ -1544,20 +1491,16 @@
           "Invalid length %u in %s in class file %s",
           length, tbl_name, CHECK_NULL);
       }
-      int cp_size = cp->length();
-      guarantee_property(
-        valid_cp_range(name_index, cp_size) &&
-          cp->tag_at(name_index).is_utf8(),
+      int cp_size = _cp->length();
+      guarantee_property(valid_symbol_at(name_index),
         "Name index %u in %s has bad constant type in class file %s",
         name_index, tbl_name, CHECK_NULL);
-      guarantee_property(
-        valid_cp_range(descriptor_index, cp_size) &&
-          cp->tag_at(descriptor_index).is_utf8(),
+      guarantee_property(valid_symbol_at(descriptor_index),
         "Signature index %u in %s has bad constant type in class file %s",
         descriptor_index, tbl_name, CHECK_NULL);
 
-      Symbol*  name = cp->symbol_at(name_index);
-      Symbol*  sig = cp->symbol_at(descriptor_index);
+      Symbol*  name = _cp->symbol_at(name_index);
+      Symbol*  sig = _cp->symbol_at(descriptor_index);
       verify_legal_field_name(name, CHECK_NULL);
       u2 extra_slot = 0;
       if (!isLVTT) {
@@ -1579,7 +1522,7 @@
 
 
 void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_index, u4* u2_index,
-                                      u1* u1_array, u2* u2_array, constantPoolHandle cp, TRAPS) {
+                                      u1* u1_array, u2* u2_array, TRAPS) {
   ClassFileStream* cfs = stream();
   u2 index = 0; // index in the array with long/double occupying two slots
   u4 i1 = *u1_index;
@@ -1591,8 +1534,7 @@
       index++;
     } else if (tag == ITEM_Object) {
       u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
-      guarantee_property(valid_cp_range(class_index, cp->length()) &&
-                         is_klass_reference(cp, class_index),
+      guarantee_property(valid_klass_reference_at(class_index),
                          "Bad class index %u in StackMap in class file %s",
                          class_index, CHECK);
     } else if (tag == ITEM_Uninitialized) {
@@ -1613,8 +1555,7 @@
   *u2_index = i2;
 }
 
-Array<u1>* ClassFileParser::parse_stackmap_table(
-    ClassLoaderData* loader_data,
+u1* ClassFileParser::parse_stackmap_table(
     u4 code_attribute_length, TRAPS) {
   if (code_attribute_length == 0)
     return NULL;
@@ -1629,18 +1570,12 @@
   if (!_need_verify && !DumpSharedSpaces) {
     return NULL;
   }
-
-  Array<u1>* stackmap_data =
-    MetadataFactory::new_array<u1>(loader_data, code_attribute_length, 0, CHECK_NULL);
-
-  memcpy((void*)stackmap_data->adr_at(0),
-         (void*)stackmap_table_start, code_attribute_length);
-  return stackmap_data;
+  return stackmap_table_start;
 }
 
 u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
                                               u4 method_attribute_length,
-                                              constantPoolHandle cp, TRAPS) {
+                                              TRAPS) {
   ClassFileStream* cfs = stream();
   cfs->guarantee_more(2, CHECK_NULL);  // checked_exceptions_length
   *checked_exceptions_length = cfs->get_u2_fast();
@@ -1657,8 +1592,7 @@
     for (int i = 0; i < len; i++) {
       checked_exception = cfs->get_u2_fast();
       check_property(
-        valid_cp_range(checked_exception, cp->length()) &&
-        is_klass_reference(cp, checked_exception),
+        valid_klass_reference_at(checked_exception),
         "Exception name has bad type at constant pool %u in class file %s",
         checked_exception, CHECK_NULL);
     }
@@ -1735,9 +1669,7 @@
 }
 
 // Sift through annotations, looking for those significant to the VM:
-void ClassFileParser::parse_annotations(ClassLoaderData* loader_data,
-                                        u1* buffer, int limit,
-                                        constantPoolHandle cp,
+void ClassFileParser::parse_annotations(u1* buffer, int limit,
                                         ClassFileParser::AnnotationCollector* coll,
                                         TRAPS) {
   // annotations := do(nann:u2) {annotation}
@@ -1767,17 +1699,17 @@
     u1* abase = buffer + index0;
     int atype = Bytes::get_Java_u2(abase + atype_off);
     int count = Bytes::get_Java_u2(abase + count_off);
-    Symbol* aname = check_symbol_at(cp, atype);
+    Symbol* aname = check_symbol_at(_cp, atype);
     if (aname == NULL)  break;  // invalid annotation name
     Symbol* member = NULL;
     if (count >= 1) {
       int member_index = Bytes::get_Java_u2(abase + member_off);
-      member = check_symbol_at(cp, member_index);
+      member = check_symbol_at(_cp, member_index);
       if (member == NULL)  break;  // invalid member name
     }
 
     // Here is where parsing particular annotations will take place.
-    AnnotationCollector::ID id = coll->annotation_index(loader_data, aname);
+    AnnotationCollector::ID id = coll->annotation_index(_loader_data, aname);
     if (id == AnnotationCollector::_unknown)  continue;
     coll->set_annotation(id);
 
@@ -1791,9 +1723,6 @@
       } else {
         coll->set_contended_group(0); // default contended group
       }
-      coll->set_contended(true);
-    } else {
-      coll->set_contended(false);
     }
   }
 }
@@ -1803,9 +1732,14 @@
                                                                 Symbol* name) {
   vmSymbols::SID sid = vmSymbols::find_sid(name);
   // Privileged code can use all annotations.  Other code silently drops some.
-  bool privileged = loader_data->is_the_null_class_loader_data() ||
-                    loader_data->is_anonymous();
+  const bool privileged = loader_data->is_the_null_class_loader_data() ||
+                          loader_data->is_ext_class_loader_data() ||
+                          loader_data->is_anonymous();
   switch (sid) {
+  case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature):
+    if (_location != _in_method)  break;  // only allow for methods
+    if (!privileged)              break;  // only allow in privileged code
+    return _method_CallerSensitive;
   case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
     if (_location != _in_method)  break;  // only allow for methods
     if (!privileged)              break;  // only allow in privileged code
@@ -1836,7 +1770,15 @@
     f->set_contended_group(contended_group());
 }
 
+ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
+  // If there's an error deallocate metadata for field annotations
+  MetadataFactory::free_array<u1>(_loader_data, _field_annotations);
+  MetadataFactory::free_array<u1>(_loader_data, _field_type_annotations);
+}
+
 void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
+  if (has_annotation(_method_CallerSensitive))
+    m->set_caller_sensitive(true);
   if (has_annotation(_method_ForceInline))
     m->set_force_inline(true);
   if (has_annotation(_method_DontInline))
@@ -1894,10 +1836,9 @@
           && _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(),
+                               _cp->symbol_at(lvt->name_cp_index)->as_utf8(),
                                CHECK);
       }
     }
@@ -1916,18 +1857,16 @@
       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(),
+                                 _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(),
+                               _cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
                                CHECK);
       } else {
         // to add generic signatures into LocalVariableTable
@@ -1939,8 +1878,7 @@
 }
 
 
-void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
-                                       ConstMethod* cm,
+void ClassFileParser::copy_method_annotations(ConstMethod* cm,
                                        u1* runtime_visible_annotations,
                                        int runtime_visible_annotations_length,
                                        u1* runtime_invisible_annotations,
@@ -1961,8 +1899,7 @@
 
   if (runtime_visible_annotations_length +
       runtime_invisible_annotations_length > 0) {
-     a = assemble_annotations(loader_data,
-                              runtime_visible_annotations,
+     a = assemble_annotations(runtime_visible_annotations,
                               runtime_visible_annotations_length,
                               runtime_invisible_annotations,
                               runtime_invisible_annotations_length,
@@ -1972,8 +1909,7 @@
 
   if (runtime_visible_parameter_annotations_length +
       runtime_invisible_parameter_annotations_length > 0) {
-    a = assemble_annotations(loader_data,
-                             runtime_visible_parameter_annotations,
+    a = assemble_annotations(runtime_visible_parameter_annotations,
                              runtime_visible_parameter_annotations_length,
                              runtime_invisible_parameter_annotations,
                              runtime_invisible_parameter_annotations_length,
@@ -1982,8 +1918,7 @@
   }
 
   if (annotation_default_length > 0) {
-    a = assemble_annotations(loader_data,
-                             annotation_default,
+    a = assemble_annotations(annotation_default,
                              annotation_default_length,
                              NULL,
                              0,
@@ -1993,8 +1928,7 @@
 
   if (runtime_visible_type_annotations_length +
       runtime_invisible_type_annotations_length > 0) {
-    a = assemble_annotations(loader_data,
-                             runtime_visible_type_annotations,
+    a = assemble_annotations(runtime_visible_type_annotations,
                              runtime_visible_type_annotations_length,
                              runtime_invisible_type_annotations,
                              runtime_invisible_type_annotations_length,
@@ -2013,9 +1947,7 @@
 // from the method back up to the containing klass. These flag values
 // are added to klass's access_flags.
 
-methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
-                                           constantPoolHandle cp,
-                                           bool is_interface,
+methodHandle ClassFileParser::parse_method(bool is_interface,
                                            AccessFlags *promoted_flags,
                                            TRAPS) {
   ClassFileStream* cfs = stream();
@@ -2026,22 +1958,20 @@
 
   int flags = cfs->get_u2_fast();
   u2 name_index = cfs->get_u2_fast();
-  int cp_size = cp->length();
+  int cp_size = _cp->length();
   check_property(
-    valid_cp_range(name_index, cp_size) &&
-      cp->tag_at(name_index).is_utf8(),
+    valid_symbol_at(name_index),
     "Illegal constant pool index %u for method name in class file %s",
     name_index, CHECK_(nullHandle));
-  Symbol*  name = cp->symbol_at(name_index);
+  Symbol*  name = _cp->symbol_at(name_index);
   verify_legal_method_name(name, CHECK_(nullHandle));
 
   u2 signature_index = cfs->get_u2_fast();
   guarantee_property(
-    valid_cp_range(signature_index, cp_size) &&
-      cp->tag_at(signature_index).is_utf8(),
+    valid_symbol_at(signature_index),
     "Illegal constant pool index %u for method signature in class file %s",
     signature_index, CHECK_(nullHandle));
-  Symbol*  signature = cp->symbol_at(signature_index);
+  Symbol*  signature = _cp->symbol_at(signature_index);
 
   AccessFlags access_flags;
   if (name == vmSymbols::class_initializer_name()) {
@@ -2097,7 +2027,8 @@
   bool parsed_checked_exceptions_attribute = false;
   bool parsed_stackmap_attribute = false;
   // stackmap attribute - JDK1.5
-  Array<u1>* stackmap_data = NULL;
+  u1* stackmap_data = NULL;
+  int stackmap_data_length = 0;
   u2 generic_signature_index = 0;
   MethodAnnotationCollector parsed_annotations;
   u1* runtime_visible_annotations = NULL;
@@ -2122,12 +2053,11 @@
     u2 method_attribute_name_index = cfs->get_u2_fast();
     u4 method_attribute_length = cfs->get_u4_fast();
     check_property(
-      valid_cp_range(method_attribute_name_index, cp_size) &&
-        cp->tag_at(method_attribute_name_index).is_utf8(),
+      valid_symbol_at(method_attribute_name_index),
       "Invalid method attribute name index %u in class file %s",
       method_attribute_name_index, CHECK_(nullHandle));
 
-    Symbol* method_attribute_name = cp->symbol_at(method_attribute_name_index);
+    Symbol* method_attribute_name = _cp->symbol_at(method_attribute_name_index);
     if (method_attribute_name == vmSymbols::tag_code()) {
       // Parse Code attribute
       if (_need_verify) {
@@ -2171,7 +2101,7 @@
       exception_table_length = cfs->get_u2_fast();
       if (exception_table_length > 0) {
         exception_table_start =
-              parse_exception_table(loader_data, code_length, exception_table_length, cp, CHECK_(nullHandle));
+              parse_exception_table(code_length, exception_table_length, CHECK_(nullHandle));
       }
 
       // Parse additional attributes in code attribute
@@ -2204,19 +2134,18 @@
         calculated_attribute_length += code_attribute_length +
                                        sizeof(code_attribute_name_index) +
                                        sizeof(code_attribute_length);
-        check_property(valid_cp_range(code_attribute_name_index, cp_size) &&
-                       cp->tag_at(code_attribute_name_index).is_utf8(),
+        check_property(valid_symbol_at(code_attribute_name_index),
                        "Invalid code attribute name index %u in class file %s",
                        code_attribute_name_index,
                        CHECK_(nullHandle));
         if (LoadLineNumberTables &&
-            cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
+            _cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
           // Parse and compress line number table
           parse_linenumber_table(code_attribute_length, code_length,
             &linenumber_table, CHECK_(nullHandle));
 
         } else if (LoadLocalVariableTables &&
-                   cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
+                   _cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
           // Parse local variable table
           if (!lvt_allocated) {
             localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
@@ -2238,7 +2167,6 @@
             parse_localvariable_table(code_length,
                                       max_locals,
                                       code_attribute_length,
-                                      cp,
                                       &localvariable_table_length[lvt_cnt],
                                       false,    // is not LVTT
                                       CHECK_(nullHandle));
@@ -2246,7 +2174,7 @@
           lvt_cnt++;
         } else if (LoadLocalVariableTypeTables &&
                    _major_version >= JAVA_1_5_VERSION &&
-                   cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
+                   _cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
           if (!lvt_allocated) {
             localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
               THREAD, u2,  INITIAL_MAX_LVT_NUMBER);
@@ -2268,19 +2196,18 @@
             parse_localvariable_table(code_length,
                                       max_locals,
                                       code_attribute_length,
-                                      cp,
                                       &localvariable_type_table_length[lvtt_cnt],
                                       true,     // is LVTT
                                       CHECK_(nullHandle));
           lvtt_cnt++;
-        } else if (UseSplitVerifier &&
-                   _major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
-                   cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
+        } else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
+                   _cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
           // Stack map is only needed by the new verifier in JDK1.5.
           if (parsed_stackmap_attribute) {
             classfile_parse_error("Multiple StackMapTable attributes in class file %s", CHECK_(nullHandle));
           }
-          stackmap_data = parse_stackmap_table(loader_data, code_attribute_length, CHECK_(nullHandle));
+          stackmap_data = parse_stackmap_table(code_attribute_length, CHECK_(nullHandle));
+          stackmap_data_length = code_attribute_length;
           parsed_stackmap_attribute = true;
         } else {
           // Skip unknown attributes
@@ -2301,7 +2228,7 @@
       checked_exceptions_start =
             parse_checked_exceptions(&checked_exceptions_length,
                                      method_attribute_length,
-                                     cp, CHECK_(nullHandle));
+                                     CHECK_(nullHandle));
     } else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
       // reject multiple method parameters
       if (method_parameters_seen) {
@@ -2359,9 +2286,8 @@
         runtime_visible_annotations_length = method_attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
-        parse_annotations(loader_data,
-            runtime_visible_annotations,
-            runtime_visible_annotations_length, cp, &parsed_annotations,
+        parse_annotations(runtime_visible_annotations,
+            runtime_visible_annotations_length, &parsed_annotations,
             CHECK_(nullHandle));
         cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
       } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
@@ -2434,18 +2360,18 @@
       0);
 
   Method* m = Method::allocate(
-      loader_data, code_length, access_flags, &sizes,
+      _loader_data, code_length, access_flags, &sizes,
       ConstMethod::NORMAL, CHECK_(nullHandle));
 
   ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
 
   // Fill in information from fixed part (access_flags already set)
-  m->set_constants(cp());
+  m->set_constants(_cp);
   m->set_name_index(name_index);
   m->set_signature_index(signature_index);
 #ifdef CC_INTERP
   // hmm is there a gc issue here??
-  ResultTypeFinder rtf(cp->symbol_at(signature_index));
+  ResultTypeFinder rtf(_cp->symbol_at(signature_index));
   m->set_result_index(rtf.type());
 #endif
 
@@ -2464,7 +2390,10 @@
   // Fill in code attribute information
   m->set_max_stack(max_stack);
   m->set_max_locals(max_locals);
-  m->constMethod()->set_stackmap_data(stackmap_data);
+  if (stackmap_data != NULL) {
+    m->constMethod()->copy_stackmap_data(_loader_data, stackmap_data,
+                                         stackmap_data_length, CHECK_NULL);
+  }
 
   // Copy byte codes
   m->set_code(code_start);
@@ -2520,7 +2449,7 @@
     parsed_annotations.apply_to(m);
 
   // Copy annotations
-  copy_method_annotations(loader_data, m->constMethod(),
+  copy_method_annotations(m->constMethod(),
                           runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           runtime_invisible_annotations,
@@ -2560,9 +2489,7 @@
 // from the methods back up to the containing klass. These flag values
 // are added to klass's access_flags.
 
-Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
-                                               constantPoolHandle cp,
-                                               bool is_interface,
+Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
                                                AccessFlags* promoted_flags,
                                                bool* has_final_method,
                                                bool* has_default_methods,
@@ -2571,15 +2498,13 @@
   cfs->guarantee_more(2, CHECK_NULL);  // length
   u2 length = cfs->get_u2_fast();
   if (length == 0) {
-    return Universe::the_empty_method_array();
+    _methods = Universe::the_empty_method_array();
   } else {
-    // FIXME: Handle leaks at later failures.
-    Array<Method*>* methods = MetadataFactory::new_array<Method*>(loader_data, length, NULL, CHECK_NULL);
+    _methods = MetadataFactory::new_array<Method*>(_loader_data, length, NULL, CHECK_NULL);
 
     HandleMark hm(THREAD);
     for (int index = 0; index < length; index++) {
-      methodHandle method = parse_method(loader_data,
-                                         cp, is_interface,
+      methodHandle method = parse_method(is_interface,
                                          promoted_flags,
                                          CHECK_NULL);
 
@@ -2590,7 +2515,7 @@
         // default method
         *has_default_methods = true;
       }
-      methods->at_put(index, method());
+      _methods->at_put(index, method());
     }
 
     if (_need_verify && length > 1) {
@@ -2603,7 +2528,7 @@
       {
         debug_only(No_Safepoint_Verifier nsv;)
         for (int i = 0; i < length; i++) {
-          Method* m = methods->at(i);
+          Method* m = _methods->at(i);
           // If no duplicates, add name/signature in hashtable names_and_sigs.
           if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) {
             dup = true;
@@ -2616,14 +2541,12 @@
                               CHECK_NULL);
       }
     }
-    return methods;
   }
+  return _methods;
 }
 
 
-Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
-                                          Array<Method*>* methods,
-                                          TRAPS) {
+intArray* ClassFileParser::sort_methods(Array<Method*>* methods) {
   int length = methods->length();
   // If JVMTI original method ordering or sharing is enabled we have to
   // remember the original class file ordering.
@@ -2641,10 +2564,11 @@
   // Note that the ordering is not alphabetical, see Symbol::fast_compare
   Method::sort_methods(methods);
 
+  intArray* method_ordering = NULL;
   // If JVMTI original method ordering or sharing is enabled construct int
   // array remembering the original ordering
   if (JvmtiExport::can_maintain_original_method_order() || DumpSharedSpaces) {
-    Array<int>* method_ordering = MetadataFactory::new_array<int>(loader_data, length, CHECK_NULL);
+    method_ordering = new intArray(length);
     for (int index = 0; index < length; index++) {
       Method* m = methods->at(index);
       int old_index = m->vtable_index();
@@ -2652,29 +2576,25 @@
       method_ordering->at_put(index, old_index);
       m->set_vtable_index(Method::invalid_vtable_index);
     }
-    return method_ordering;
-  } else {
-    return Universe::the_empty_int_array();
   }
+  return method_ordering;
 }
 
 
-void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS) {
+void ClassFileParser::parse_classfile_sourcefile_attribute(TRAPS) {
   ClassFileStream* cfs = stream();
   cfs->guarantee_more(2, CHECK);  // sourcefile_index
   u2 sourcefile_index = cfs->get_u2_fast();
   check_property(
-    valid_cp_range(sourcefile_index, cp->length()) &&
-      cp->tag_at(sourcefile_index).is_utf8(),
+    valid_symbol_at(sourcefile_index),
     "Invalid SourceFile attribute at constant pool index %u in class file %s",
     sourcefile_index, CHECK);
-  set_class_sourcefile(cp->symbol_at(sourcefile_index));
+  set_class_sourcefile(_cp->symbol_at(sourcefile_index));
 }
 
 
 
-void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
-                                                                       int length, TRAPS) {
+void ClassFileParser::parse_classfile_source_debug_extension_attribute(int length, TRAPS) {
   ClassFileStream* cfs = stream();
   u1* sde_buffer = cfs->get_u1_buffer();
   assert(sde_buffer != NULL, "null sde buffer");
@@ -2698,12 +2618,10 @@
 #define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
 
 // Return number of classes in the inner classes attribute table
-u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data,
-                                                            u1* inner_classes_attribute_start,
+u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
                                                             bool parsed_enclosingmethod_attribute,
                                                             u2 enclosing_method_class_index,
                                                             u2 enclosing_method_method_index,
-                                                            constantPoolHandle cp,
                                                             TRAPS) {
   ClassFileStream* cfs = stream();
   u1* current_mark = cfs->current();
@@ -2724,33 +2642,31 @@
   //    enclosing_method_class_index,
   //    enclosing_method_method_index]
   int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
-  // FIXME: Will leak on exceptions.
-  Array<u2>* inner_classes = MetadataFactory::new_array<u2>(loader_data, size, CHECK_0);
+  Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+  _inner_classes = inner_classes;
+
   int index = 0;
-  int cp_size = cp->length();
+  int cp_size = _cp->length();
   cfs->guarantee_more(8 * length, CHECK_0);  // 4-tuples of u2
   for (int n = 0; n < length; n++) {
     // Inner class index
     u2 inner_class_info_index = cfs->get_u2_fast();
     check_property(
       inner_class_info_index == 0 ||
-        (valid_cp_range(inner_class_info_index, cp_size) &&
-        is_klass_reference(cp, inner_class_info_index)),
+        valid_klass_reference_at(inner_class_info_index),
       "inner_class_info_index %u has bad constant type in class file %s",
       inner_class_info_index, CHECK_0);
     // Outer class index
     u2 outer_class_info_index = cfs->get_u2_fast();
     check_property(
       outer_class_info_index == 0 ||
-        (valid_cp_range(outer_class_info_index, cp_size) &&
-        is_klass_reference(cp, outer_class_info_index)),
+        valid_klass_reference_at(outer_class_info_index),
       "outer_class_info_index %u has bad constant type in class file %s",
       outer_class_info_index, CHECK_0);
     // Inner class name
     u2 inner_name_index = cfs->get_u2_fast();
     check_property(
-      inner_name_index == 0 || (valid_cp_range(inner_name_index, cp_size) &&
-        cp->tag_at(inner_name_index).is_utf8()),
+      inner_name_index == 0 || valid_symbol_at(inner_name_index),
       "inner_name_index %u has bad constant type in class file %s",
       inner_name_index, CHECK_0);
     if (_need_verify) {
@@ -2794,33 +2710,27 @@
   }
   assert(index == size, "wrong size");
 
-  // Update InstanceKlass with inner class info.
-  set_class_inner_classes(inner_classes);
-
   // Restore buffer's current position.
   cfs->set_current(current_mark);
 
   return length;
 }
 
-void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) {
+void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) {
   set_class_synthetic_flag(true);
 }
 
-void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) {
+void ClassFileParser::parse_classfile_signature_attribute(TRAPS) {
   ClassFileStream* cfs = stream();
   u2 signature_index = cfs->get_u2(CHECK);
   check_property(
-    valid_cp_range(signature_index, cp->length()) &&
-      cp->tag_at(signature_index).is_utf8(),
+    valid_symbol_at(signature_index),
     "Invalid constant pool index %u in Signature attribute in class file %s",
     signature_index, CHECK);
-  set_class_generic_signature(cp->symbol_at(signature_index));
+  set_class_generic_signature(_cp->symbol_at(signature_index));
 }
 
-void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderData* loader_data,
-                                                                  constantPoolHandle cp,
-                                                                  u4 attribute_byte_length, TRAPS) {
+void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_byte_length, TRAPS) {
   ClassFileStream* cfs = stream();
   u1* current_start = cfs->current();
 
@@ -2841,10 +2751,14 @@
   // The array begins with a series of short[2] pairs, one for each tuple.
   int index_size = (attribute_array_length * 2);
 
-  Array<u2>* operands = MetadataFactory::new_array<u2>(loader_data, index_size + operand_count, CHECK);
+  Array<u2>* operands = MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);
+
+  // Eagerly assign operands so they will be deallocated with the constant
+  // pool if there is an error.
+  _cp->set_operands(operands);
 
   int operand_fill_index = index_size;
-  int cp_size = cp->length();
+  int cp_size = _cp->length();
 
   for (int n = 0; n < attribute_array_length; n++) {
     // Store a 32-bit offset into the header of the operand array.
@@ -2856,7 +2770,7 @@
     u2 argument_count = cfs->get_u2_fast();
     check_property(
       valid_cp_range(bootstrap_method_index, cp_size) &&
-      cp->tag_at(bootstrap_method_index).is_method_handle(),
+      _cp->tag_at(bootstrap_method_index).is_method_handle(),
       "bootstrap_method_index %u has bad constant type in class file %s",
       bootstrap_method_index,
       CHECK);
@@ -2868,7 +2782,7 @@
       u2 argument_index = cfs->get_u2_fast();
       check_property(
         valid_cp_range(argument_index, cp_size) &&
-        cp->tag_at(argument_index).is_loadable_constant(),
+        _cp->tag_at(argument_index).is_loadable_constant(),
         "argument_index %u has bad constant type in class file %s",
         argument_index,
         CHECK);
@@ -2883,17 +2797,13 @@
   guarantee_property(current_end == current_start + attribute_byte_length,
                      "Bad length on BootstrapMethods in class file %s",
                      CHECK);
-
-  cp->set_operands(operands);
 }
 
-void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
-                                                 constantPoolHandle cp,
-                                                 ClassFileParser::ClassAnnotationCollector* parsed_annotations,
+void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotationCollector* parsed_annotations,
                                                  TRAPS) {
   ClassFileStream* cfs = stream();
   // Set inner classes attribute to default sentinel
-  set_class_inner_classes(Universe::the_empty_short_array());
+  _inner_classes = Universe::the_empty_short_array();
   cfs->guarantee_more(2, CHECK);  // attributes_count
   u2 attributes_count = cfs->get_u2_fast();
   bool parsed_sourcefile_attribute = false;
@@ -2918,11 +2828,10 @@
     u2 attribute_name_index = cfs->get_u2_fast();
     u4 attribute_length = cfs->get_u4_fast();
     check_property(
-      valid_cp_range(attribute_name_index, cp->length()) &&
-        cp->tag_at(attribute_name_index).is_utf8(),
+      valid_symbol_at(attribute_name_index),
       "Attribute name has bad constant pool index %u in class file %s",
       attribute_name_index, CHECK);
-    Symbol* tag = cp->symbol_at(attribute_name_index);
+    Symbol* tag = _cp->symbol_at(attribute_name_index);
     if (tag == vmSymbols::tag_source_file()) {
       // Check for SourceFile tag
       if (_need_verify) {
@@ -2933,10 +2842,10 @@
       } else {
         parsed_sourcefile_attribute = true;
       }
-      parse_classfile_sourcefile_attribute(cp, CHECK);
+      parse_classfile_sourcefile_attribute(CHECK);
     } else if (tag == vmSymbols::tag_source_debug_extension()) {
       // Check for SourceDebugExtension tag
-      parse_classfile_source_debug_extension_attribute(cp, (int)attribute_length, CHECK);
+      parse_classfile_source_debug_extension_attribute((int)attribute_length, CHECK);
     } else if (tag == vmSymbols::tag_inner_classes()) {
       // Check for InnerClasses tag
       if (parsed_innerclasses_attribute) {
@@ -2955,7 +2864,7 @@
           "Invalid Synthetic classfile attribute length %u in class file %s",
           attribute_length, CHECK);
       }
-      parse_classfile_synthetic_attribute(cp, CHECK);
+      parse_classfile_synthetic_attribute(CHECK);
     } else if (tag == vmSymbols::tag_deprecated()) {
       // Check for Deprecatd tag - 4276120
       if (attribute_length != 0) {
@@ -2970,15 +2879,13 @@
             "Wrong Signature attribute length %u in class file %s",
             attribute_length, CHECK);
         }
-        parse_classfile_signature_attribute(cp, CHECK);
+        parse_classfile_signature_attribute(CHECK);
       } else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
-        parse_annotations(loader_data,
-                          runtime_visible_annotations,
+        parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
-                          cp,
                           parsed_annotations,
                           CHECK);
         cfs->skip_u1(runtime_visible_annotations_length, CHECK);
@@ -3000,13 +2907,11 @@
           classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
         }
         // Validate the constant pool indices and types
-        if (!cp->is_within_bounds(enclosing_method_class_index) ||
-            !is_klass_reference(cp, enclosing_method_class_index)) {
-          classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
-        }
+        check_property(valid_klass_reference_at(enclosing_method_class_index),
+          "Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
         if (enclosing_method_method_index != 0 &&
-            (!cp->is_within_bounds(enclosing_method_method_index) ||
-             !cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
+            (!_cp->is_within_bounds(enclosing_method_method_index) ||
+             !_cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
           classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
         }
       } else if (tag == vmSymbols::tag_bootstrap_methods() &&
@@ -3014,7 +2919,7 @@
         if (parsed_bootstrap_methods_attribute)
           classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
         parsed_bootstrap_methods_attribute = true;
-        parse_classfile_bootstrap_methods_attribute(loader_data, cp, attribute_length, CHECK);
+        parse_classfile_bootstrap_methods_attribute(attribute_length, CHECK);
       } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) {
         runtime_visible_type_annotations_length = attribute_length;
         runtime_visible_type_annotations = cfs->get_u1_buffer();
@@ -3035,29 +2940,24 @@
       cfs->skip_u1(attribute_length, CHECK);
     }
   }
-  AnnotationArray* annotations = assemble_annotations(loader_data,
-                                                      runtime_visible_annotations,
-                                                      runtime_visible_annotations_length,
-                                                      runtime_invisible_annotations,
-                                                      runtime_invisible_annotations_length,
-                                                      CHECK);
-  set_class_annotations(annotations);
-  AnnotationArray* 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);
-  set_class_type_annotations(type_annotations);
+  _annotations = assemble_annotations(runtime_visible_annotations,
+                                      runtime_visible_annotations_length,
+                                      runtime_invisible_annotations,
+                                      runtime_invisible_annotations_length,
+                                      CHECK);
+  _type_annotations = assemble_annotations(runtime_visible_type_annotations,
+                                           runtime_visible_type_annotations_length,
+                                           runtime_invisible_type_annotations,
+                                           runtime_invisible_type_annotations_length,
+                                           CHECK);
 
   if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
     u2 num_of_classes = parse_classfile_inner_classes_attribute(
-                            loader_data,
                             inner_classes_attribute_start,
                             parsed_innerclasses_attribute,
                             enclosing_method_class_index,
                             enclosing_method_method_index,
-                            cp, CHECK);
+                            CHECK);
     if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
       guarantee_property(
         inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
@@ -3085,18 +2985,43 @@
   if (_sde_buffer != NULL) {
     k->set_source_debug_extension(_sde_buffer, _sde_length);
   }
-  k->set_inner_classes(_inner_classes);
 }
 
-AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
-                                                       u1* runtime_visible_annotations,
+// Transfer ownership of metadata allocated to the InstanceKlass.
+void ClassFileParser::apply_parsed_class_metadata(
+                                            instanceKlassHandle this_klass,
+                                            int java_fields_count, TRAPS) {
+  // Assign annotations if needed
+  if (_annotations != NULL || _type_annotations != NULL ||
+      _fields_annotations != NULL || _fields_type_annotations != NULL) {
+    Annotations* annotations = Annotations::allocate(_loader_data, CHECK);
+    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);
+  }
+
+  _cp->set_pool_holder(this_klass());
+  this_klass->set_constants(_cp);
+  this_klass->set_fields(_fields, java_fields_count);
+  this_klass->set_methods(_methods);
+  this_klass->set_inner_classes(_inner_classes);
+  this_klass->set_local_interfaces(_local_interfaces);
+  this_klass->set_transitive_interfaces(_transitive_interfaces);
+
+  // Clear out these fields so they don't get deallocated by the destructor
+  clear_class_metadata();
+}
+
+AnnotationArray* ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
                                                        int runtime_visible_annotations_length,
                                                        u1* runtime_invisible_annotations,
                                                        int runtime_invisible_annotations_length, TRAPS) {
   AnnotationArray* annotations = NULL;
   if (runtime_visible_annotations != NULL ||
       runtime_invisible_annotations != NULL) {
-    annotations = MetadataFactory::new_array<u1>(loader_data,
+    annotations = MetadataFactory::new_array<u1>(_loader_data,
                                           runtime_visible_annotations_length +
                                           runtime_invisible_annotations_length,
                                           CHECK_(annotations));
@@ -3144,6 +3069,581 @@
 #endif // ndef PRODUCT
 
 
+instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index,
+                                                       TRAPS) {
+  instanceKlassHandle super_klass;
+  if (super_class_index == 0) {
+    check_property(_class_name == vmSymbols::java_lang_Object(),
+                   "Invalid superclass index %u in class file %s",
+                   super_class_index,
+                   CHECK_NULL);
+  } else {
+    check_property(valid_klass_reference_at(super_class_index),
+                   "Invalid superclass index %u in class file %s",
+                   super_class_index,
+                   CHECK_NULL);
+    // The class name should be legal because it is checked when parsing constant pool.
+    // However, make sure it is not an array type.
+    bool is_array = false;
+    if (_cp->tag_at(super_class_index).is_klass()) {
+      super_klass = instanceKlassHandle(THREAD, _cp->resolved_klass_at(super_class_index));
+      if (_need_verify)
+        is_array = super_klass->oop_is_array();
+    } else if (_need_verify) {
+      is_array = (_cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
+    }
+    if (_need_verify) {
+      guarantee_property(!is_array,
+                        "Bad superclass name in class file %s", CHECK_NULL);
+    }
+  }
+  return super_klass;
+}
+
+
+// Values needed for oopmap and InstanceKlass creation
+class FieldLayoutInfo : public StackObj {
+ public:
+  int*          nonstatic_oop_offsets;
+  unsigned int* nonstatic_oop_counts;
+  unsigned int  nonstatic_oop_map_count;
+  unsigned int  total_oop_map_count;
+  int           instance_size;
+  int           nonstatic_field_size;
+  int           static_field_size;
+  bool          has_nonstatic_fields;
+};
+
+// Layout fields and fill in FieldLayoutInfo.  Could use more refactoring!
+void ClassFileParser::layout_fields(Handle class_loader,
+                                    FieldAllocationCount* fac,
+                                    ClassAnnotationCollector* parsed_annotations,
+                                    FieldLayoutInfo* info,
+                                    TRAPS) {
+
+  // get the padding width from the option
+  // TODO: Ask VM about specific CPU we are running on
+  int pad_size = ContendedPaddingWidth;
+
+  // Field size and offset computation
+  int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size();
+#ifndef PRODUCT
+  int orig_nonstatic_field_size = 0;
+#endif
+  int next_static_oop_offset;
+  int next_static_double_offset;
+  int next_static_word_offset;
+  int next_static_short_offset;
+  int next_static_byte_offset;
+  int next_nonstatic_oop_offset;
+  int next_nonstatic_double_offset;
+  int next_nonstatic_word_offset;
+  int next_nonstatic_short_offset;
+  int next_nonstatic_byte_offset;
+  int next_nonstatic_type_offset;
+  int first_nonstatic_oop_offset;
+  int first_nonstatic_field_offset;
+  int next_nonstatic_field_offset;
+  int next_nonstatic_padded_offset;
+
+  // Count the contended fields by type.
+  int nonstatic_contended_count = 0;
+  FieldAllocationCount fac_contended;
+  for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
+    FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
+    if (fs.is_contended()) {
+      fac_contended.count[atype]++;
+      if (!fs.access_flags().is_static()) {
+        nonstatic_contended_count++;
+      }
+    }
+  }
+  int contended_count = nonstatic_contended_count;
+
+
+  // Calculate the starting byte offsets
+  next_static_oop_offset      = InstanceMirrorKlass::offset_of_static_fields();
+  next_static_double_offset   = next_static_oop_offset +
+                                ((fac->count[STATIC_OOP]) * heapOopSize);
+  if ( fac->count[STATIC_DOUBLE] &&
+       (Universe::field_type_should_be_aligned(T_DOUBLE) ||
+        Universe::field_type_should_be_aligned(T_LONG)) ) {
+    next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
+  }
+
+  next_static_word_offset     = next_static_double_offset +
+                                ((fac->count[STATIC_DOUBLE]) * BytesPerLong);
+  next_static_short_offset    = next_static_word_offset +
+                                ((fac->count[STATIC_WORD]) * BytesPerInt);
+  next_static_byte_offset     = next_static_short_offset +
+                                ((fac->count[STATIC_SHORT]) * BytesPerShort);
+
+  first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
+                                 nonstatic_field_size * heapOopSize;
+
+  // class is contended, pad before all the fields
+  if (parsed_annotations->is_contended()) {
+    first_nonstatic_field_offset += pad_size;
+  }
+
+  next_nonstatic_field_offset = first_nonstatic_field_offset;
+
+  unsigned int nonstatic_double_count = fac->count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
+  unsigned int nonstatic_word_count   = fac->count[NONSTATIC_WORD]   - fac_contended.count[NONSTATIC_WORD];
+  unsigned int nonstatic_short_count  = fac->count[NONSTATIC_SHORT]  - fac_contended.count[NONSTATIC_SHORT];
+  unsigned int nonstatic_byte_count   = fac->count[NONSTATIC_BYTE]   - fac_contended.count[NONSTATIC_BYTE];
+  unsigned int nonstatic_oop_count    = fac->count[NONSTATIC_OOP]    - fac_contended.count[NONSTATIC_OOP];
+
+  bool super_has_nonstatic_fields =
+          (_super_klass() != NULL && _super_klass->has_nonstatic_fields());
+  bool has_nonstatic_fields = super_has_nonstatic_fields ||
+          ((nonstatic_double_count + nonstatic_word_count +
+            nonstatic_short_count + nonstatic_byte_count +
+            nonstatic_oop_count) != 0);
+
+
+  // Prepare list of oops for oop map generation.
+  int* nonstatic_oop_offsets;
+  unsigned int* nonstatic_oop_counts;
+  unsigned int nonstatic_oop_map_count = 0;
+
+  nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
+            THREAD, int, nonstatic_oop_count + 1);
+  nonstatic_oop_counts  = NEW_RESOURCE_ARRAY_IN_THREAD(
+            THREAD, unsigned int, nonstatic_oop_count + 1);
+
+  first_nonstatic_oop_offset = 0; // will be set for first oop field
+
+#ifndef PRODUCT
+  if( PrintCompactFieldsSavings ) {
+    next_nonstatic_double_offset = next_nonstatic_field_offset +
+                                   (nonstatic_oop_count * heapOopSize);
+    if ( nonstatic_double_count > 0 ) {
+      next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong);
+    }
+    next_nonstatic_word_offset  = next_nonstatic_double_offset +
+                                  (nonstatic_double_count * BytesPerLong);
+    next_nonstatic_short_offset = next_nonstatic_word_offset +
+                                  (nonstatic_word_count * BytesPerInt);
+    next_nonstatic_byte_offset  = next_nonstatic_short_offset +
+                                  (nonstatic_short_count * BytesPerShort);
+    next_nonstatic_type_offset  = align_size_up((next_nonstatic_byte_offset +
+                                  nonstatic_byte_count ), heapOopSize );
+    orig_nonstatic_field_size   = nonstatic_field_size +
+    ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
+  }
+#endif
+  bool compact_fields   = CompactFields;
+  int  allocation_style = FieldsAllocationStyle;
+  if( allocation_style < 0 || allocation_style > 2 ) { // Out of range?
+    assert(false, "0 <= FieldsAllocationStyle <= 2");
+    allocation_style = 1; // Optimistic
+  }
+
+  // The next classes have predefined hard-coded fields offsets
+  // (see in JavaClasses::compute_hard_coded_offsets()).
+  // Use default fields allocation order for them.
+  if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() &&
+      (_class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
+       _class_name == vmSymbols::java_lang_Class() ||
+       _class_name == vmSymbols::java_lang_ClassLoader() ||
+       _class_name == vmSymbols::java_lang_ref_Reference() ||
+       _class_name == vmSymbols::java_lang_ref_SoftReference() ||
+       _class_name == vmSymbols::java_lang_StackTraceElement() ||
+       _class_name == vmSymbols::java_lang_String() ||
+       _class_name == vmSymbols::java_lang_Throwable() ||
+       _class_name == vmSymbols::java_lang_Boolean() ||
+       _class_name == vmSymbols::java_lang_Character() ||
+       _class_name == vmSymbols::java_lang_Float() ||
+       _class_name == vmSymbols::java_lang_Double() ||
+       _class_name == vmSymbols::java_lang_Byte() ||
+       _class_name == vmSymbols::java_lang_Short() ||
+       _class_name == vmSymbols::java_lang_Integer() ||
+       _class_name == vmSymbols::java_lang_Long())) {
+    allocation_style = 0;     // Allocate oops first
+    compact_fields   = false; // Don't compact fields
+  }
+
+  if( allocation_style == 0 ) {
+    // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
+    next_nonstatic_oop_offset    = next_nonstatic_field_offset;
+    next_nonstatic_double_offset = next_nonstatic_oop_offset +
+                                    (nonstatic_oop_count * heapOopSize);
+  } else if( allocation_style == 1 ) {
+    // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
+    next_nonstatic_double_offset = next_nonstatic_field_offset;
+  } else if( allocation_style == 2 ) {
+    // Fields allocation: oops fields in super and sub classes are together.
+    if( nonstatic_field_size > 0 && _super_klass() != NULL &&
+        _super_klass->nonstatic_oop_map_size() > 0 ) {
+      unsigned int map_count = _super_klass->nonstatic_oop_map_count();
+      OopMapBlock* first_map = _super_klass->start_of_nonstatic_oop_maps();
+      OopMapBlock* last_map = first_map + map_count - 1;
+      int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
+      if (next_offset == next_nonstatic_field_offset) {
+        allocation_style = 0;   // allocate oops first
+        next_nonstatic_oop_offset    = next_nonstatic_field_offset;
+        next_nonstatic_double_offset = next_nonstatic_oop_offset +
+                                       (nonstatic_oop_count * heapOopSize);
+      }
+    }
+    if( allocation_style == 2 ) {
+      allocation_style = 1;     // allocate oops last
+      next_nonstatic_double_offset = next_nonstatic_field_offset;
+    }
+  } else {
+    ShouldNotReachHere();
+  }
+
+  int nonstatic_oop_space_count   = 0;
+  int nonstatic_word_space_count  = 0;
+  int nonstatic_short_space_count = 0;
+  int nonstatic_byte_space_count  = 0;
+  int nonstatic_oop_space_offset;
+  int nonstatic_word_space_offset;
+  int nonstatic_short_space_offset;
+  int nonstatic_byte_space_offset;
+
+  if( nonstatic_double_count > 0 ) {
+    int offset = next_nonstatic_double_offset;
+    next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
+    if( compact_fields && offset != next_nonstatic_double_offset ) {
+      // Allocate available fields into the gap before double field.
+      int length = next_nonstatic_double_offset - offset;
+      assert(length == BytesPerInt, "");
+      nonstatic_word_space_offset = offset;
+      if( nonstatic_word_count > 0 ) {
+        nonstatic_word_count      -= 1;
+        nonstatic_word_space_count = 1; // Only one will fit
+        length -= BytesPerInt;
+        offset += BytesPerInt;
+      }
+      nonstatic_short_space_offset = offset;
+      while( length >= BytesPerShort && nonstatic_short_count > 0 ) {
+        nonstatic_short_count       -= 1;
+        nonstatic_short_space_count += 1;
+        length -= BytesPerShort;
+        offset += BytesPerShort;
+      }
+      nonstatic_byte_space_offset = offset;
+      while( length > 0 && nonstatic_byte_count > 0 ) {
+        nonstatic_byte_count       -= 1;
+        nonstatic_byte_space_count += 1;
+        length -= 1;
+      }
+      // Allocate oop field in the gap if there are no other fields for that.
+      nonstatic_oop_space_offset = offset;
+      if( length >= heapOopSize && nonstatic_oop_count > 0 &&
+          allocation_style != 0 ) { // when oop fields not first
+        nonstatic_oop_count      -= 1;
+        nonstatic_oop_space_count = 1; // Only one will fit
+        length -= heapOopSize;
+        offset += heapOopSize;
+      }
+    }
+  }
+
+  next_nonstatic_word_offset  = next_nonstatic_double_offset +
+                                (nonstatic_double_count * BytesPerLong);
+  next_nonstatic_short_offset = next_nonstatic_word_offset +
+                                (nonstatic_word_count * BytesPerInt);
+  next_nonstatic_byte_offset  = next_nonstatic_short_offset +
+                                (nonstatic_short_count * BytesPerShort);
+  next_nonstatic_padded_offset = next_nonstatic_byte_offset +
+                                nonstatic_byte_count;
+
+  // let oops jump before padding with this allocation style
+  if( allocation_style == 1 ) {
+    next_nonstatic_oop_offset = next_nonstatic_padded_offset;
+    if( nonstatic_oop_count > 0 ) {
+      next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
+    }
+    next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
+  }
+
+  // Iterate over fields again and compute correct offsets.
+  // The field allocation type was temporarily stored in the offset slot.
+  // oop fields are located before non-oop fields (static and non-static).
+  for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
+
+    // skip already laid out fields
+    if (fs.is_offset_set()) continue;
+
+    // contended instance fields are handled below
+    if (fs.is_contended() && !fs.access_flags().is_static()) continue;
+
+    int real_offset;
+    FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
+
+    // pack the rest of the fields
+    switch (atype) {
+      case STATIC_OOP:
+        real_offset = next_static_oop_offset;
+        next_static_oop_offset += heapOopSize;
+        break;
+      case STATIC_BYTE:
+        real_offset = next_static_byte_offset;
+        next_static_byte_offset += 1;
+        break;
+      case STATIC_SHORT:
+        real_offset = next_static_short_offset;
+        next_static_short_offset += BytesPerShort;
+        break;
+      case STATIC_WORD:
+        real_offset = next_static_word_offset;
+        next_static_word_offset += BytesPerInt;
+        break;
+      case STATIC_DOUBLE:
+        real_offset = next_static_double_offset;
+        next_static_double_offset += BytesPerLong;
+        break;
+      case NONSTATIC_OOP:
+        if( nonstatic_oop_space_count > 0 ) {
+          real_offset = nonstatic_oop_space_offset;
+          nonstatic_oop_space_offset += heapOopSize;
+          nonstatic_oop_space_count  -= 1;
+        } else {
+          real_offset = next_nonstatic_oop_offset;
+          next_nonstatic_oop_offset += heapOopSize;
+        }
+        // Update oop maps
+        if( nonstatic_oop_map_count > 0 &&
+            nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
+            real_offset -
+            int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
+            heapOopSize ) {
+          // Extend current oop map
+          nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
+        } else {
+          // Create new oop map
+          nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
+          nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
+          nonstatic_oop_map_count += 1;
+          if( first_nonstatic_oop_offset == 0 ) { // Undefined
+            first_nonstatic_oop_offset = real_offset;
+          }
+        }
+        break;
+      case NONSTATIC_BYTE:
+        if( nonstatic_byte_space_count > 0 ) {
+          real_offset = nonstatic_byte_space_offset;
+          nonstatic_byte_space_offset += 1;
+          nonstatic_byte_space_count  -= 1;
+        } else {
+          real_offset = next_nonstatic_byte_offset;
+          next_nonstatic_byte_offset += 1;
+        }
+        break;
+      case NONSTATIC_SHORT:
+        if( nonstatic_short_space_count > 0 ) {
+          real_offset = nonstatic_short_space_offset;
+          nonstatic_short_space_offset += BytesPerShort;
+          nonstatic_short_space_count  -= 1;
+        } else {
+          real_offset = next_nonstatic_short_offset;
+          next_nonstatic_short_offset += BytesPerShort;
+        }
+        break;
+      case NONSTATIC_WORD:
+        if( nonstatic_word_space_count > 0 ) {
+          real_offset = nonstatic_word_space_offset;
+          nonstatic_word_space_offset += BytesPerInt;
+          nonstatic_word_space_count  -= 1;
+        } else {
+          real_offset = next_nonstatic_word_offset;
+          next_nonstatic_word_offset += BytesPerInt;
+        }
+        break;
+      case NONSTATIC_DOUBLE:
+        real_offset = next_nonstatic_double_offset;
+        next_nonstatic_double_offset += BytesPerLong;
+        break;
+      default:
+        ShouldNotReachHere();
+    }
+    fs.set_offset(real_offset);
+  }
+
+
+  // Handle the contended cases.
+  //
+  // Each contended field should not intersect the cache line with another contended field.
+  // In the absence of alignment information, we end up with pessimistically separating
+  // the fields with full-width padding.
+  //
+  // Additionally, this should not break alignment for the fields, so we round the alignment up
+  // for each field.
+  if (contended_count > 0) {
+
+    // if there is at least one contended field, we need to have pre-padding for them
+    if (nonstatic_contended_count > 0) {
+      next_nonstatic_padded_offset += pad_size;
+    }
+
+    // collect all contended groups
+    BitMap bm(_cp->size());
+    for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
+      // skip already laid out fields
+      if (fs.is_offset_set()) continue;
+
+      if (fs.is_contended()) {
+        bm.set_bit(fs.contended_group());
+      }
+    }
+
+    int current_group = -1;
+    while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
+
+      for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
+
+        // skip already laid out fields
+        if (fs.is_offset_set()) continue;
+
+        // skip non-contended fields and fields from different group
+        if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
+
+        // handle statics below
+        if (fs.access_flags().is_static()) continue;
+
+        int real_offset;
+        FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
+
+        switch (atype) {
+          case NONSTATIC_BYTE:
+            next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1);
+            real_offset = next_nonstatic_padded_offset;
+            next_nonstatic_padded_offset += 1;
+            break;
+
+          case NONSTATIC_SHORT:
+            next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort);
+            real_offset = next_nonstatic_padded_offset;
+            next_nonstatic_padded_offset += BytesPerShort;
+            break;
+
+          case NONSTATIC_WORD:
+            next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt);
+            real_offset = next_nonstatic_padded_offset;
+            next_nonstatic_padded_offset += BytesPerInt;
+            break;
+
+          case NONSTATIC_DOUBLE:
+            next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong);
+            real_offset = next_nonstatic_padded_offset;
+            next_nonstatic_padded_offset += BytesPerLong;
+            break;
+
+          case NONSTATIC_OOP:
+            next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize);
+            real_offset = next_nonstatic_padded_offset;
+            next_nonstatic_padded_offset += heapOopSize;
+
+            // Create new oop map
+            nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
+            nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
+            nonstatic_oop_map_count += 1;
+            if( first_nonstatic_oop_offset == 0 ) { // Undefined
+              first_nonstatic_oop_offset = real_offset;
+            }
+            break;
+
+          default:
+            ShouldNotReachHere();
+        }
+
+        if (fs.contended_group() == 0) {
+          // Contended group defines the equivalence class over the fields:
+          // the fields within the same contended group are not inter-padded.
+          // The only exception is default group, which does not incur the
+          // equivalence, and so requires intra-padding.
+          next_nonstatic_padded_offset += pad_size;
+        }
+
+        fs.set_offset(real_offset);
+      } // for
+
+      // Start laying out the next group.
+      // Note that this will effectively pad the last group in the back;
+      // this is expected to alleviate memory contention effects for
+      // subclass fields and/or adjacent object.
+      // If this was the default group, the padding is already in place.
+      if (current_group != 0) {
+        next_nonstatic_padded_offset += pad_size;
+      }
+    }
+
+    // handle static fields
+  }
+
+  // Size of instances
+  int notaligned_offset = next_nonstatic_padded_offset;
+
+  // Entire class is contended, pad in the back.
+  // This helps to alleviate memory contention effects for subclass fields
+  // and/or adjacent object.
+  if (parsed_annotations->is_contended()) {
+    notaligned_offset += pad_size;
+  }
+
+  int next_static_type_offset     = align_size_up(next_static_byte_offset, wordSize);
+  int static_field_size           = (next_static_type_offset -
+                                InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
+
+  next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
+  nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
+                                 - first_nonstatic_field_offset)/heapOopSize);
+
+  next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
+  int instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
+
+  assert(instance_size == align_object_size(align_size_up(
+         (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations->is_contended()) ? pad_size : 0)),
+          wordSize) / wordSize), "consistent layout helper value");
+
+  // Number of non-static oop map blocks allocated at end of klass.
+  const unsigned int total_oop_map_count =
+    compute_oop_map_count(_super_klass, nonstatic_oop_map_count,
+                          first_nonstatic_oop_offset);
+
+#ifndef PRODUCT
+  if( PrintCompactFieldsSavings ) {
+    ResourceMark rm;
+    if( nonstatic_field_size < orig_nonstatic_field_size ) {
+      tty->print("[Saved %d of %d bytes in %s]\n",
+               (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
+               orig_nonstatic_field_size*heapOopSize,
+               _class_name);
+    } else if( nonstatic_field_size > orig_nonstatic_field_size ) {
+      tty->print("[Wasted %d over %d bytes in %s]\n",
+               (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
+               orig_nonstatic_field_size*heapOopSize,
+               _class_name);
+    }
+  }
+
+  if (PrintFieldLayout) {
+    print_field_layout(_class_name,
+          _fields,
+          _cp,
+          instance_size,
+          first_nonstatic_field_offset,
+          next_nonstatic_field_offset,
+          next_static_type_offset);
+  }
+
+#endif
+  // Pass back information needed for InstanceKlass creation
+  info->nonstatic_oop_offsets = nonstatic_oop_offsets;
+  info->nonstatic_oop_counts = nonstatic_oop_counts;
+  info->nonstatic_oop_map_count = nonstatic_oop_map_count;
+  info->total_oop_map_count = total_oop_map_count;
+  info->instance_size = instance_size;
+  info->static_field_size = static_field_size;
+  info->nonstatic_field_size = nonstatic_field_size;
+  info->has_nonstatic_fields = has_nonstatic_fields;
+}
+
+
 instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
                                                     ClassLoaderData* loader_data,
                                                     Handle protection_domain,
@@ -3176,7 +3676,7 @@
                             jt->get_thread_stat()->perf_timers_addr(),
                             PerfClassTraceTime::PARSE_CLASS);
 
-  init_parsed_class_attributes();
+  init_parsed_class_attributes(loader_data);
 
   if (JvmtiExport::should_post_class_file_load_hook()) {
     // Get the cached class file bytes (if any) from the class that
@@ -3271,8 +3771,7 @@
   _relax_verify = Verifier::relax_verify_for(class_loader());
 
   // Constant pool
-  constantPoolHandle cp = parse_constant_pool(loader_data, CHECK_(nullHandle));
-  ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
+  constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
 
   int cp_size = cp->length();
 
@@ -3290,7 +3789,6 @@
   access_flags.set_flags(flags);
 
   // This class and superclass
-  instanceKlassHandle super_klass;
   u2 this_class_index = cfs->get_u2_fast();
   check_property(
     valid_cp_range(this_class_index, cp_size) &&
@@ -3345,59 +3843,27 @@
     }
 
     u2 super_class_index = cfs->get_u2_fast();
-    if (super_class_index == 0) {
-      check_property(class_name == vmSymbols::java_lang_Object(),
-                     "Invalid superclass index %u in class file %s",
-                     super_class_index,
-                     CHECK_(nullHandle));
-    } else {
-      check_property(valid_cp_range(super_class_index, cp_size) &&
-                     is_klass_reference(cp, super_class_index),
-                     "Invalid superclass index %u in class file %s",
-                     super_class_index,
-                     CHECK_(nullHandle));
-      // The class name should be legal because it is checked when parsing constant pool.
-      // However, make sure it is not an array type.
-      bool is_array = false;
-      if (cp->tag_at(super_class_index).is_klass()) {
-        super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index));
-        if (_need_verify)
-          is_array = super_klass->oop_is_array();
-      } else if (_need_verify) {
-        is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
-      }
-      if (_need_verify) {
-        guarantee_property(!is_array,
-                          "Bad superclass name in class file %s", CHECK_(nullHandle));
-      }
-    }
+    instanceKlassHandle super_klass = parse_super_class(super_class_index,
+                                                        CHECK_NULL);
 
     // Interfaces
     u2 itfs_len = cfs->get_u2_fast();
-    Array<Klass*>* local_interfaces;
-    if (itfs_len == 0) {
-      local_interfaces = Universe::the_empty_klass_array();
-    } else {
-      local_interfaces = parse_interfaces(
-          cp, itfs_len, loader_data, protection_domain, _class_name,
-          &has_default_methods, CHECK_(nullHandle));
-    }
+    Array<Klass*>* local_interfaces =
+      parse_interfaces(itfs_len, protection_domain, _class_name,
+                       &has_default_methods, CHECK_(nullHandle));
 
     u2 java_fields_count = 0;
     // Fields (offsets are filled in later)
     FieldAllocationCount fac;
-    Array<AnnotationArray*>* fields_annotations = NULL;
-    Array<AnnotationArray*>* fields_type_annotations = NULL;
-    Array<u2>* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations,
-                                          &fields_type_annotations,
-                                          &java_fields_count,
-                                          CHECK_(nullHandle));
+    Array<u2>* fields = parse_fields(class_name,
+                                     access_flags.is_interface(),
+                                     &fac, &java_fields_count,
+                                     CHECK_(nullHandle));
     // Methods
     bool has_final_method = false;
     AccessFlags promoted_flags;
     promoted_flags.set_flags(0);
-    Array<Method*>* methods = parse_methods(loader_data,
-                                            cp, access_flags.is_interface(),
+    Array<Method*>* methods = parse_methods(access_flags.is_interface(),
                                             &promoted_flags,
                                             &has_final_method,
                                             &has_default_methods,
@@ -3405,7 +3871,7 @@
 
     // Additional attributes
     ClassAnnotationCollector parsed_annotations;
-    parse_classfile_attributes(loader_data, cp, &parsed_annotations, CHECK_(nullHandle));
+    parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
 
     // Make sure this is the end of class file stream
     guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
@@ -3452,13 +3918,15 @@
       }
     }
 
+    // save super klass for error handling.
+    _super_klass = super_klass;
+
     // Compute the transitive list of all unique interfaces implemented by this class
-    Array<Klass*>* transitive_interfaces = compute_transitive_interfaces(loader_data, super_klass, local_interfaces, CHECK_(nullHandle));
+    _transitive_interfaces =
+          compute_transitive_interfaces(super_klass, local_interfaces, CHECK_(nullHandle));
 
     // sort methods
-    Array<int>* method_ordering = sort_methods(loader_data,
-                                               methods,
-                                               CHECK_(nullHandle));
+    intArray* method_ordering = sort_methods(methods);
 
     // promote flags from parse_methods() to the klass' flags
     access_flags.add_promoted_flags(promoted_flags.as_int());
@@ -3476,587 +3944,14 @@
                                                       CHECK_(nullHandle));
 
     // Size of Java itable (in words)
-    itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces);
-
-    // get the padding width from the option
-    // TODO: Ask VM about specific CPU we are running on
-    int pad_size = ContendedPaddingWidth;
-
-    // Field size and offset computation
-    int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size();
-#ifndef PRODUCT
-    int orig_nonstatic_field_size = 0;
-#endif
-    int next_static_oop_offset;
-    int next_static_double_offset;
-    int next_static_word_offset;
-    int next_static_short_offset;
-    int next_static_byte_offset;
-    int next_static_padded_offset;
-    int next_nonstatic_oop_offset;
-    int next_nonstatic_double_offset;
-    int next_nonstatic_word_offset;
-    int next_nonstatic_short_offset;
-    int next_nonstatic_byte_offset;
-    int next_nonstatic_type_offset;
-    int first_nonstatic_oop_offset;
-    int first_nonstatic_field_offset;
-    int next_nonstatic_field_offset;
-    int next_nonstatic_padded_offset;
-
-    // Count the contended fields by type.
-    int static_contended_count = 0;
-    int nonstatic_contended_count = 0;
-    FieldAllocationCount fac_contended;
-    for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
-      FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
-      if (fs.is_contended()) {
-        fac_contended.count[atype]++;
-        if (fs.access_flags().is_static()) {
-          static_contended_count++;
-        } else {
-          nonstatic_contended_count++;
-        }
-      }
-    }
-    int contended_count = static_contended_count + nonstatic_contended_count;
-
-
-    // Calculate the starting byte offsets
-    next_static_oop_offset      = InstanceMirrorKlass::offset_of_static_fields();
-
-    // class is contended, pad before all the fields
-    if (parsed_annotations.is_contended()) {
-      next_static_oop_offset += pad_size;
-    }
-
-    next_static_double_offset   = next_static_oop_offset +
-                                  ((fac.count[STATIC_OOP] - fac_contended.count[STATIC_OOP]) * heapOopSize);
-    if ( fac.count[STATIC_DOUBLE] &&
-         (Universe::field_type_should_be_aligned(T_DOUBLE) ||
-          Universe::field_type_should_be_aligned(T_LONG)) ) {
-      next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
-    }
-
-    next_static_word_offset     = next_static_double_offset +
-                                  ((fac.count[STATIC_DOUBLE] - fac_contended.count[STATIC_DOUBLE]) * BytesPerLong);
-    next_static_short_offset    = next_static_word_offset +
-                                  ((fac.count[STATIC_WORD]   - fac_contended.count[STATIC_WORD]) * BytesPerInt);
-    next_static_byte_offset     = next_static_short_offset +
-                                  ((fac.count[STATIC_SHORT]  - fac_contended.count[STATIC_SHORT]) * BytesPerShort);
-    next_static_padded_offset   = next_static_byte_offset +
-                                  ((fac.count[STATIC_BYTE]   - fac_contended.count[STATIC_BYTE]) * 1);
-
-    first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
-                                   nonstatic_field_size * heapOopSize;
-
-    // class is contended, pad before all the fields
-    if (parsed_annotations.is_contended()) {
-      first_nonstatic_field_offset += pad_size;
-    }
-
-    next_nonstatic_field_offset = first_nonstatic_field_offset;
-
-    unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
-    unsigned int nonstatic_word_count   = fac.count[NONSTATIC_WORD]   - fac_contended.count[NONSTATIC_WORD];
-    unsigned int nonstatic_short_count  = fac.count[NONSTATIC_SHORT]  - fac_contended.count[NONSTATIC_SHORT];
-    unsigned int nonstatic_byte_count   = fac.count[NONSTATIC_BYTE]   - fac_contended.count[NONSTATIC_BYTE];
-    unsigned int nonstatic_oop_count    = fac.count[NONSTATIC_OOP]    - fac_contended.count[NONSTATIC_OOP];
-
-    bool super_has_nonstatic_fields =
-            (super_klass() != NULL && super_klass->has_nonstatic_fields());
-    bool has_nonstatic_fields  =  super_has_nonstatic_fields ||
-            ((nonstatic_double_count + nonstatic_word_count +
-              nonstatic_short_count + nonstatic_byte_count +
-              nonstatic_oop_count) != 0);
-
-
-    // Prepare list of oops for oop map generation.
-    int* nonstatic_oop_offsets;
-    unsigned int* nonstatic_oop_counts;
-    unsigned int nonstatic_oop_map_count = 0;
-
-    nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
-              THREAD, int, nonstatic_oop_count + 1);
-    nonstatic_oop_counts  = NEW_RESOURCE_ARRAY_IN_THREAD(
-              THREAD, unsigned int, nonstatic_oop_count + 1);
-
-    first_nonstatic_oop_offset = 0; // will be set for first oop field
-
-#ifndef PRODUCT
-    if( PrintCompactFieldsSavings ) {
-      next_nonstatic_double_offset = next_nonstatic_field_offset +
-                                     (nonstatic_oop_count * heapOopSize);
-      if ( nonstatic_double_count > 0 ) {
-        next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong);
-      }
-      next_nonstatic_word_offset  = next_nonstatic_double_offset +
-                                    (nonstatic_double_count * BytesPerLong);
-      next_nonstatic_short_offset = next_nonstatic_word_offset +
-                                    (nonstatic_word_count * BytesPerInt);
-      next_nonstatic_byte_offset  = next_nonstatic_short_offset +
-                                    (nonstatic_short_count * BytesPerShort);
-      next_nonstatic_type_offset  = align_size_up((next_nonstatic_byte_offset +
-                                    nonstatic_byte_count ), heapOopSize );
-      orig_nonstatic_field_size   = nonstatic_field_size +
-      ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
-    }
-#endif
-    bool compact_fields   = CompactFields;
-    int  allocation_style = FieldsAllocationStyle;
-    if( allocation_style < 0 || allocation_style > 2 ) { // Out of range?
-      assert(false, "0 <= FieldsAllocationStyle <= 2");
-      allocation_style = 1; // Optimistic
-    }
-
-    // The next classes have predefined hard-coded fields offsets
-    // (see in JavaClasses::compute_hard_coded_offsets()).
-    // Use default fields allocation order for them.
-    if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() &&
-        (class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
-         class_name == vmSymbols::java_lang_Class() ||
-         class_name == vmSymbols::java_lang_ClassLoader() ||
-         class_name == vmSymbols::java_lang_ref_Reference() ||
-         class_name == vmSymbols::java_lang_ref_SoftReference() ||
-         class_name == vmSymbols::java_lang_StackTraceElement() ||
-         class_name == vmSymbols::java_lang_String() ||
-         class_name == vmSymbols::java_lang_Throwable() ||
-         class_name == vmSymbols::java_lang_Boolean() ||
-         class_name == vmSymbols::java_lang_Character() ||
-         class_name == vmSymbols::java_lang_Float() ||
-         class_name == vmSymbols::java_lang_Double() ||
-         class_name == vmSymbols::java_lang_Byte() ||
-         class_name == vmSymbols::java_lang_Short() ||
-         class_name == vmSymbols::java_lang_Integer() ||
-         class_name == vmSymbols::java_lang_Long())) {
-      allocation_style = 0;     // Allocate oops first
-      compact_fields   = false; // Don't compact fields
-    }
-
-    if( allocation_style == 0 ) {
-      // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
-      next_nonstatic_oop_offset    = next_nonstatic_field_offset;
-      next_nonstatic_double_offset = next_nonstatic_oop_offset +
-                                      (nonstatic_oop_count * heapOopSize);
-    } else if( allocation_style == 1 ) {
-      // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
-      next_nonstatic_double_offset = next_nonstatic_field_offset;
-    } else if( allocation_style == 2 ) {
-      // Fields allocation: oops fields in super and sub classes are together.
-      if( nonstatic_field_size > 0 && super_klass() != NULL &&
-          super_klass->nonstatic_oop_map_size() > 0 ) {
-        int map_count = super_klass->nonstatic_oop_map_count();
-        OopMapBlock* first_map = super_klass->start_of_nonstatic_oop_maps();
-        OopMapBlock* last_map = first_map + map_count - 1;
-        int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
-        if (next_offset == next_nonstatic_field_offset) {
-          allocation_style = 0;   // allocate oops first
-          next_nonstatic_oop_offset    = next_nonstatic_field_offset;
-          next_nonstatic_double_offset = next_nonstatic_oop_offset +
-                                         (nonstatic_oop_count * heapOopSize);
-        }
-      }
-      if( allocation_style == 2 ) {
-        allocation_style = 1;     // allocate oops last
-        next_nonstatic_double_offset = next_nonstatic_field_offset;
-      }
-    } else {
-      ShouldNotReachHere();
-    }
-
-    int nonstatic_oop_space_count   = 0;
-    int nonstatic_word_space_count  = 0;
-    int nonstatic_short_space_count = 0;
-    int nonstatic_byte_space_count  = 0;
-    int nonstatic_oop_space_offset;
-    int nonstatic_word_space_offset;
-    int nonstatic_short_space_offset;
-    int nonstatic_byte_space_offset;
-
-    if( nonstatic_double_count > 0 ) {
-      int offset = next_nonstatic_double_offset;
-      next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
-      if( compact_fields && offset != next_nonstatic_double_offset ) {
-        // Allocate available fields into the gap before double field.
-        int length = next_nonstatic_double_offset - offset;
-        assert(length == BytesPerInt, "");
-        nonstatic_word_space_offset = offset;
-        if( nonstatic_word_count > 0 ) {
-          nonstatic_word_count      -= 1;
-          nonstatic_word_space_count = 1; // Only one will fit
-          length -= BytesPerInt;
-          offset += BytesPerInt;
-        }
-        nonstatic_short_space_offset = offset;
-        while( length >= BytesPerShort && nonstatic_short_count > 0 ) {
-          nonstatic_short_count       -= 1;
-          nonstatic_short_space_count += 1;
-          length -= BytesPerShort;
-          offset += BytesPerShort;
-        }
-        nonstatic_byte_space_offset = offset;
-        while( length > 0 && nonstatic_byte_count > 0 ) {
-          nonstatic_byte_count       -= 1;
-          nonstatic_byte_space_count += 1;
-          length -= 1;
-        }
-        // Allocate oop field in the gap if there are no other fields for that.
-        nonstatic_oop_space_offset = offset;
-        if( length >= heapOopSize && nonstatic_oop_count > 0 &&
-            allocation_style != 0 ) { // when oop fields not first
-          nonstatic_oop_count      -= 1;
-          nonstatic_oop_space_count = 1; // Only one will fit
-          length -= heapOopSize;
-          offset += heapOopSize;
-        }
-      }
-    }
-
-    next_nonstatic_word_offset  = next_nonstatic_double_offset +
-                                  (nonstatic_double_count * BytesPerLong);
-    next_nonstatic_short_offset = next_nonstatic_word_offset +
-                                  (nonstatic_word_count * BytesPerInt);
-    next_nonstatic_byte_offset  = next_nonstatic_short_offset +
-                                  (nonstatic_short_count * BytesPerShort);
-    next_nonstatic_padded_offset = next_nonstatic_byte_offset +
-                                  nonstatic_byte_count;
-
-    // let oops jump before padding with this allocation style
-    if( allocation_style == 1 ) {
-      next_nonstatic_oop_offset = next_nonstatic_padded_offset;
-      if( nonstatic_oop_count > 0 ) {
-        next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
-      }
-      next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
-    }
-
-    // Iterate over fields again and compute correct offsets.
-    // The field allocation type was temporarily stored in the offset slot.
-    // oop fields are located before non-oop fields (static and non-static).
-    for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
-
-      // skip already laid out fields
-      if (fs.is_offset_set()) continue;
-
-      // contended fields are handled below
-      if (fs.is_contended()) continue;
-
-      int real_offset;
-      FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
-
-      // pack the rest of the fields
-      switch (atype) {
-        case STATIC_OOP:
-          real_offset = next_static_oop_offset;
-          next_static_oop_offset += heapOopSize;
-          break;
-        case STATIC_BYTE:
-          real_offset = next_static_byte_offset;
-          next_static_byte_offset += 1;
-          break;
-        case STATIC_SHORT:
-          real_offset = next_static_short_offset;
-          next_static_short_offset += BytesPerShort;
-          break;
-        case STATIC_WORD:
-          real_offset = next_static_word_offset;
-          next_static_word_offset += BytesPerInt;
-          break;
-        case STATIC_DOUBLE:
-          real_offset = next_static_double_offset;
-          next_static_double_offset += BytesPerLong;
-          break;
-        case NONSTATIC_OOP:
-          if( nonstatic_oop_space_count > 0 ) {
-            real_offset = nonstatic_oop_space_offset;
-            nonstatic_oop_space_offset += heapOopSize;
-            nonstatic_oop_space_count  -= 1;
-          } else {
-            real_offset = next_nonstatic_oop_offset;
-            next_nonstatic_oop_offset += heapOopSize;
-          }
-          // Update oop maps
-          if( nonstatic_oop_map_count > 0 &&
-              nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
-              real_offset -
-              int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
-              heapOopSize ) {
-            // Extend current oop map
-            nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
-          } else {
-            // Create new oop map
-            nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
-            nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
-            nonstatic_oop_map_count += 1;
-            if( first_nonstatic_oop_offset == 0 ) { // Undefined
-              first_nonstatic_oop_offset = real_offset;
-            }
-          }
-          break;
-        case NONSTATIC_BYTE:
-          if( nonstatic_byte_space_count > 0 ) {
-            real_offset = nonstatic_byte_space_offset;
-            nonstatic_byte_space_offset += 1;
-            nonstatic_byte_space_count  -= 1;
-          } else {
-            real_offset = next_nonstatic_byte_offset;
-            next_nonstatic_byte_offset += 1;
-          }
-          break;
-        case NONSTATIC_SHORT:
-          if( nonstatic_short_space_count > 0 ) {
-            real_offset = nonstatic_short_space_offset;
-            nonstatic_short_space_offset += BytesPerShort;
-            nonstatic_short_space_count  -= 1;
-          } else {
-            real_offset = next_nonstatic_short_offset;
-            next_nonstatic_short_offset += BytesPerShort;
-          }
-          break;
-        case NONSTATIC_WORD:
-          if( nonstatic_word_space_count > 0 ) {
-            real_offset = nonstatic_word_space_offset;
-            nonstatic_word_space_offset += BytesPerInt;
-            nonstatic_word_space_count  -= 1;
-          } else {
-            real_offset = next_nonstatic_word_offset;
-            next_nonstatic_word_offset += BytesPerInt;
-          }
-          break;
-        case NONSTATIC_DOUBLE:
-          real_offset = next_nonstatic_double_offset;
-          next_nonstatic_double_offset += BytesPerLong;
-          break;
-        default:
-          ShouldNotReachHere();
-      }
-      fs.set_offset(real_offset);
-    }
-
-
-    // Handle the contended cases.
-    //
-    // Each contended field should not intersect the cache line with another contended field.
-    // In the absence of alignment information, we end up with pessimistically separating
-    // the fields with full-width padding.
-    //
-    // Additionally, this should not break alignment for the fields, so we round the alignment up
-    // for each field.
-    if (contended_count > 0) {
-
-      // if there is at least one contended field, we need to have pre-padding for them
-      if (nonstatic_contended_count > 0) {
-        next_nonstatic_padded_offset += pad_size;
-      }
-
-      // collect all contended groups
-      BitMap bm(cp->size());
-      for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
-        // skip already laid out fields
-        if (fs.is_offset_set()) continue;
-
-        if (fs.is_contended()) {
-          bm.set_bit(fs.contended_group());
-        }
-      }
-
-      int current_group = -1;
-      while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
-
-        for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
-
-          // skip already laid out fields
-          if (fs.is_offset_set()) continue;
-
-          // skip non-contended fields and fields from different group
-          if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
-
-          // handle statics below
-          if (fs.access_flags().is_static()) continue;
-
-          int real_offset;
-          FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
-
-          switch (atype) {
-            case NONSTATIC_BYTE:
-              next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1);
-              real_offset = next_nonstatic_padded_offset;
-              next_nonstatic_padded_offset += 1;
-              break;
-
-            case NONSTATIC_SHORT:
-              next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort);
-              real_offset = next_nonstatic_padded_offset;
-              next_nonstatic_padded_offset += BytesPerShort;
-              break;
-
-            case NONSTATIC_WORD:
-              next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt);
-              real_offset = next_nonstatic_padded_offset;
-              next_nonstatic_padded_offset += BytesPerInt;
-              break;
-
-            case NONSTATIC_DOUBLE:
-              next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong);
-              real_offset = next_nonstatic_padded_offset;
-              next_nonstatic_padded_offset += BytesPerLong;
-              break;
-
-            case NONSTATIC_OOP:
-              next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize);
-              real_offset = next_nonstatic_padded_offset;
-              next_nonstatic_padded_offset += heapOopSize;
-
-              // Create new oop map
-              nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
-              nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
-              nonstatic_oop_map_count += 1;
-              if( first_nonstatic_oop_offset == 0 ) { // Undefined
-                first_nonstatic_oop_offset = real_offset;
-              }
-              break;
-
-            default:
-              ShouldNotReachHere();
-          }
-
-          if (fs.contended_group() == 0) {
-            // Contended group defines the equivalence class over the fields:
-            // the fields within the same contended group are not inter-padded.
-            // The only exception is default group, which does not incur the
-            // equivalence, and so requires intra-padding.
-            next_nonstatic_padded_offset += pad_size;
-          }
-
-          fs.set_offset(real_offset);
-        } // for
-
-        // Start laying out the next group.
-        // Note that this will effectively pad the last group in the back;
-        // this is expected to alleviate memory contention effects for
-        // subclass fields and/or adjacent object.
-        // If this was the default group, the padding is already in place.
-        if (current_group != 0) {
-          next_nonstatic_padded_offset += pad_size;
-        }
-      }
-
-      // handle static fields
-
-      // if there is at least one contended field, we need to have pre-padding for them
-      if (static_contended_count > 0) {
-        next_static_padded_offset += pad_size;
-      }
-
-      current_group = -1;
-      while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
-
-        for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
-
-          // skip already laid out fields
-          if (fs.is_offset_set()) continue;
-
-          // skip non-contended fields and fields from different group
-          if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
-
-          // non-statics already handled above
-          if (!fs.access_flags().is_static()) continue;
-
-          int real_offset;
-          FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
-
-          switch (atype) {
-
-            case STATIC_BYTE:
-              next_static_padded_offset = align_size_up(next_static_padded_offset, 1);
-              real_offset = next_static_padded_offset;
-              next_static_padded_offset += 1;
-              break;
-
-            case STATIC_SHORT:
-              next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerShort);
-              real_offset = next_static_padded_offset;
-              next_static_padded_offset += BytesPerShort;
-              break;
-
-            case STATIC_WORD:
-              next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerInt);
-              real_offset = next_static_padded_offset;
-              next_static_padded_offset += BytesPerInt;
-              break;
-
-            case STATIC_DOUBLE:
-              next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerLong);
-              real_offset = next_static_padded_offset;
-              next_static_padded_offset += BytesPerLong;
-              break;
-
-            case STATIC_OOP:
-              next_static_padded_offset = align_size_up(next_static_padded_offset, heapOopSize);
-              real_offset = next_static_padded_offset;
-              next_static_padded_offset += heapOopSize;
-              break;
-
-            default:
-              ShouldNotReachHere();
-          }
-
-          if (fs.contended_group() == 0) {
-            // Contended group defines the equivalence class over the fields:
-            // the fields within the same contended group are not inter-padded.
-            // The only exception is default group, which does not incur the
-            // equivalence, and so requires intra-padding.
-            next_static_padded_offset += pad_size;
-          }
-
-          fs.set_offset(real_offset);
-        } // for
-
-        // Start laying out the next group.
-        // Note that this will effectively pad the last group in the back;
-        // this is expected to alleviate memory contention effects for
-        // subclass fields and/or adjacent object.
-        // If this was the default group, the padding is already in place.
-        if (current_group != 0) {
-          next_static_padded_offset += pad_size;
-        }
-
-      }
-
-    } // handle contended
-
-    // Size of instances
-    int instance_size;
-
-    int notaligned_offset = next_nonstatic_padded_offset;
-
-    // Entire class is contended, pad in the back.
-    // This helps to alleviate memory contention effects for subclass fields
-    // and/or adjacent object.
-    if (parsed_annotations.is_contended()) {
-      notaligned_offset += pad_size;
-      next_static_padded_offset += pad_size;
-    }
-
-    int next_static_type_offset     = align_size_up(next_static_padded_offset, wordSize);
-    int static_field_size           = (next_static_type_offset -
-                                  InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
-
-    next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
-    nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
-                                   - first_nonstatic_field_offset)/heapOopSize);
-
-    next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
-    instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
-
-    assert(instance_size == align_object_size(align_size_up(
-                (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations.is_contended()) ? pad_size : 0)),
-            wordSize) / wordSize), "consistent layout helper value");
-
-    // Number of non-static oop map blocks allocated at end of klass.
-    const unsigned int total_oop_map_count =
-      compute_oop_map_count(super_klass, nonstatic_oop_map_count,
-                            first_nonstatic_oop_offset);
+    itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);
+
+    FieldLayoutInfo info;
+    layout_fields(class_loader, &fac, &parsed_annotations, &info, CHECK_NULL);
+
+    int total_oop_map_size2 =
+          InstanceKlass::nonstatic_oop_map_size(info.total_oop_map_count);
+
     // Compute reference type
     ReferenceType rt;
     if (super_klass() == NULL) {
@@ -4066,53 +3961,42 @@
     }
 
     // We can now create the basic Klass* for this klass
-    int total_oop_map_size2 =
-      InstanceKlass::nonstatic_oop_map_size(total_oop_map_count);
-
-    Klass* ik = InstanceKlass::allocate_instance_klass(loader_data,
-                                                       vtable_size,
-                                                       itable_size,
-                                                       static_field_size,
-                                                       total_oop_map_size2,
-                                                       rt,
-                                                       access_flags,
-                                                       name,
-                                                       super_klass(),
-                                                       !host_klass.is_null(),
-                                                       CHECK_(nullHandle));
-
-    // Add all classes to our internal class loader list here,
-    // including classes in the bootstrap (NULL) class loader.
-    loader_data->add_class(ik);
-
-    instanceKlassHandle this_klass (THREAD, ik);
-
-    assert(this_klass->static_field_size() == static_field_size, "sanity");
-    assert(this_klass->nonstatic_oop_map_count() == total_oop_map_count,
+    _klass = InstanceKlass::allocate_instance_klass(loader_data,
+                                                    vtable_size,
+                                                    itable_size,
+                                                    info.static_field_size,
+                                                    total_oop_map_size2,
+                                                    rt,
+                                                    access_flags,
+                                                    name,
+                                                    super_klass(),
+                                                    !host_klass.is_null(),
+                                                    CHECK_(nullHandle));
+    instanceKlassHandle this_klass (THREAD, _klass);
+
+    assert(this_klass->static_field_size() == info.static_field_size, "sanity");
+    assert(this_klass->nonstatic_oop_map_count() == info.total_oop_map_count,
            "sanity");
 
     // Fill in information already parsed
     this_klass->set_should_verify_class(verify);
-    jint lh = Klass::instance_layout_helper(instance_size, false);
+    jint lh = Klass::instance_layout_helper(info.instance_size, false);
     this_klass->set_layout_helper(lh);
     assert(this_klass->oop_is_instance(), "layout is correct");
-    assert(this_klass->size_helper() == instance_size, "correct size_helper");
+    assert(this_klass->size_helper() == info.instance_size, "correct size_helper");
     // Not yet: supers are done below to support the new subtype-checking fields
     //this_klass->set_super(super_klass());
     this_klass->set_class_loader_data(loader_data);
-    this_klass->set_nonstatic_field_size(nonstatic_field_size);
-    this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
+    this_klass->set_nonstatic_field_size(info.nonstatic_field_size);
+    this_klass->set_has_nonstatic_fields(info.has_nonstatic_fields);
     this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]);
-    cp->set_pool_holder(this_klass());
-    error_handler.set_in_error(false);   // turn off error handler for cp
-    this_klass->set_constants(cp());
-    this_klass->set_local_interfaces(local_interfaces);
-    this_klass->set_fields(fields, java_fields_count);
-    this_klass->set_methods(methods);
+
+    apply_parsed_class_metadata(this_klass, java_fields_count, CHECK_NULL);
+
     if (has_final_method) {
       this_klass->set_has_final_method();
     }
-    this_klass->set_method_ordering(method_ordering);
+    this_klass->copy_method_ordering(method_ordering, CHECK_NULL);
     // The InstanceKlass::_methods_jmethod_ids cache and the
     // InstanceKlass::_methods_cached_itable_indices cache are
     // both managed on the assumption that the initial cache
@@ -4124,17 +4008,6 @@
     if (is_anonymous())  // I am well known to myself
       cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
 
-    // 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);
     this_klass->set_major_version(major_version);
     this_klass->set_has_default_methods(has_default_methods);
@@ -4169,8 +4042,6 @@
       this_klass->set_has_miranda_methods(); // then set a flag
     }
 
-    this_klass->set_transitive_interfaces(transitive_interfaces);
-
     // Fill in information needed to compute superclasses.
     this_klass->initialize_supers(super_klass(), CHECK_(nullHandle));
 
@@ -4179,7 +4050,7 @@
 
     // Compute transitive closure of interfaces this class implements
     // Do final class setup
-    fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
+    fill_oop_maps(this_klass, info.nonstatic_oop_map_count, info.nonstatic_oop_offsets, info.nonstatic_oop_counts);
 
     // Fill in has_finalizer, has_vanilla_constructor, and layout_helper
     set_precomputed_flags(this_klass);
@@ -4278,35 +4149,6 @@
       }
     }
 
-#ifndef PRODUCT
-    if( PrintCompactFieldsSavings ) {
-      ResourceMark rm;
-      if( nonstatic_field_size < orig_nonstatic_field_size ) {
-        tty->print("[Saved %d of %d bytes in %s]\n",
-                 (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
-                 orig_nonstatic_field_size*heapOopSize,
-                 this_klass->external_name());
-      } else if( nonstatic_field_size > orig_nonstatic_field_size ) {
-        tty->print("[Wasted %d over %d bytes in %s]\n",
-                 (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
-                 orig_nonstatic_field_size*heapOopSize,
-                 this_klass->external_name());
-      }
-    }
-#endif
-
-#ifndef PRODUCT
-    if (PrintFieldLayout) {
-      print_field_layout(name,
-            fields,
-            cp,
-            instance_size,
-            first_nonstatic_field_offset,
-            next_nonstatic_field_offset,
-            next_static_type_offset);
-    }
-#endif
-
     // preserve result across HandleMark
     preserve_this_klass = this_klass();
   }
@@ -4316,9 +4158,40 @@
   instanceKlassHandle this_klass (THREAD, preserve_this_klass);
   debug_only(this_klass->verify();)
 
+  // Clear class if no error has occurred so destructor doesn't deallocate it
+  _klass = NULL;
   return this_klass;
 }
 
+// Destructor to clean up if there's an error
+ClassFileParser::~ClassFileParser() {
+  MetadataFactory::free_metadata(_loader_data, _cp);
+  MetadataFactory::free_array<u2>(_loader_data, _fields);
+
+  // Free methods
+  InstanceKlass::deallocate_methods(_loader_data, _methods);
+
+  // beware of the Universe::empty_blah_array!!
+  if (_inner_classes != Universe::the_empty_short_array()) {
+    MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
+  }
+
+  // Free interfaces
+  InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(),
+                                       _local_interfaces, _transitive_interfaces);
+
+  MetadataFactory::free_array<u1>(_loader_data, _annotations);
+  MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
+  Annotations::free_contents(_loader_data, _fields_annotations);
+  Annotations::free_contents(_loader_data, _fields_type_annotations);
+
+  clear_class_metadata();
+
+  // deallocate the klass if already created.
+  MetadataFactory::free_metadata(_loader_data, _klass);
+  _klass = NULL;
+}
+
 void ClassFileParser::print_field_layout(Symbol* name,
                                          Array<u2>* fields,
                                          constantPoolHandle cp,
@@ -4510,7 +4383,7 @@
   }
 }
 
-// utility method for appending and array with check for duplicates
+// utility methods for appending an array with check for duplicates
 
 void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
   // iterate over new interfaces
@@ -4522,8 +4395,9 @@
   }
 }
 
-
-Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* loader_data, instanceKlassHandle super, Array<Klass*>* local_ifs, TRAPS) {
+Array<Klass*>* ClassFileParser::compute_transitive_interfaces(
+                                        instanceKlassHandle super,
+                                        Array<Klass*>* local_ifs, TRAPS) {
   // Compute maximum size for transitive interfaces
   int max_transitive_size = 0;
   int super_size = 0;
@@ -4570,7 +4444,7 @@
     // length will be less than the max_transitive_size if duplicates were removed
     int length = result->length();
     assert(length <= max_transitive_size, "just checking");
-    Array<Klass*>* new_result = MetadataFactory::new_array<Klass*>(loader_data, length, CHECK_NULL);
+    Array<Klass*>* new_result = MetadataFactory::new_array<Klass*>(_loader_data, length, CHECK_NULL);
     for (int i = 0; i < length; i++) {
       Klass* e = result->at(i);
         assert(e != NULL, "just checking");
@@ -4580,7 +4454,6 @@
   }
 }
 
-
 void ClassFileParser::check_super_class_access(instanceKlassHandle this_klass, TRAPS) {
   Klass* super = this_klass->super();
   if ((super != NULL) &&
--- a/src/share/vm/classfile/classFileParser.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/classFileParser.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -34,6 +34,7 @@
 #include "classfile/symbolTable.hpp"
 
 class FieldAllocationCount;
+class FieldLayoutInfo;
 
 
 // Parser for for .class files
@@ -47,6 +48,7 @@
   u2   _major_version;
   u2   _minor_version;
   Symbol* _class_name;
+  ClassLoaderData* _loader_data;
   KlassHandle _host_klass;
   GrowableArray<Handle>* _cp_patches; // overrides for CP entries
 
@@ -58,39 +60,66 @@
 
   // class attributes parsed before the instance klass is created:
   bool       _synthetic_flag;
+  int        _sde_length;
+  char*      _sde_buffer;
   Symbol*    _sourcefile;
   Symbol*    _generic_signature;
-  char*      _sde_buffer;
-  int        _sde_length;
-  Array<u2>* _inner_classes;
+
+  // Metadata created before the instance klass is created.  Must be deallocated
+  // if not transferred to the InstanceKlass upon successful class loading
+  // in which case these pointers have been set to NULL.
+  instanceKlassHandle _super_klass;
+  ConstantPool*    _cp;
+  Array<u2>*       _fields;
+  Array<Method*>*  _methods;
+  Array<u2>*       _inner_classes;
+  Array<Klass*>*   _local_interfaces;
+  Array<Klass*>*   _transitive_interfaces;
   AnnotationArray* _annotations;
   AnnotationArray* _type_annotations;
+  Array<AnnotationArray*>* _fields_annotations;
+  Array<AnnotationArray*>* _fields_type_annotations;
+  InstanceKlass*   _klass;  // InstanceKlass once created.
 
   void set_class_synthetic_flag(bool x)           { _synthetic_flag = x; }
   void set_class_sourcefile(Symbol* x)            { _sourcefile = x; }
   void set_class_generic_signature(Symbol* x)     { _generic_signature = x; }
   void set_class_sde_buffer(char* x, int len)     { _sde_buffer = x; _sde_length = len; }
-  void set_class_inner_classes(Array<u2>* x)      { _inner_classes = x; }
-  void set_class_annotations(AnnotationArray* x)  { _annotations = x; }
-  void set_class_type_annotations(AnnotationArray* x)  { _type_annotations = x; }
-  void init_parsed_class_attributes() {
+
+  void init_parsed_class_attributes(ClassLoaderData* loader_data) {
+    _loader_data = loader_data;
     _synthetic_flag = false;
     _sourcefile = NULL;
     _generic_signature = NULL;
     _sde_buffer = NULL;
     _sde_length = 0;
-    _annotations = _type_annotations = NULL;
     // initialize the other flags too:
     _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
     _max_bootstrap_specifier_index = -1;
+    clear_class_metadata();
+    _klass = NULL;
   }
   void apply_parsed_class_attributes(instanceKlassHandle k);  // update k
+  void apply_parsed_class_metadata(instanceKlassHandle k, int fields_count, TRAPS);
+  void clear_class_metadata() {
+    // metadata created before the instance klass is created.  Must be
+    // deallocated if classfile parsing returns an error.
+    _cp = NULL;
+    _fields = NULL;
+    _methods = NULL;
+    _inner_classes = NULL;
+    _local_interfaces = NULL;
+    _transitive_interfaces = NULL;
+    _annotations = _type_annotations = NULL;
+    _fields_annotations = _fields_type_annotations = NULL;
+  }
 
   class AnnotationCollector {
   public:
     enum Location { _in_field, _in_method, _in_class };
     enum ID {
       _unknown = 0,
+      _method_CallerSensitive,
       _method_ForceInline,
       _method_DontInline,
       _method_LambdaForm_Compiled,
@@ -121,14 +150,29 @@
     void set_contended_group(u2 group) { _contended_group = group; }
     u2 contended_group() { return _contended_group; }
 
-    void set_contended(bool contended) { set_annotation(_sun_misc_Contended); }
     bool is_contended() { return has_annotation(_sun_misc_Contended); }
   };
+
+  // This class also doubles as a holder for metadata cleanup.
   class FieldAnnotationCollector: public AnnotationCollector {
+    ClassLoaderData* _loader_data;
+    AnnotationArray* _field_annotations;
+    AnnotationArray* _field_type_annotations;
   public:
-    FieldAnnotationCollector() : AnnotationCollector(_in_field) { }
+    FieldAnnotationCollector(ClassLoaderData* loader_data) :
+                                 AnnotationCollector(_in_field),
+                                 _loader_data(loader_data),
+                                 _field_annotations(NULL),
+                                 _field_type_annotations(NULL) {}
     void apply_to(FieldInfo* f);
+    ~FieldAnnotationCollector();
+    AnnotationArray* field_annotations()      { return _field_annotations; }
+    AnnotationArray* field_type_annotations() { return _field_type_annotations; }
+
+    void set_field_annotations(AnnotationArray* a)      { _field_annotations = a; }
+    void set_field_type_annotations(AnnotationArray* a) { _field_type_annotations = a; }
   };
+
   class MethodAnnotationCollector: public AnnotationCollector {
   public:
     MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
@@ -152,38 +196,30 @@
   void set_stream(ClassFileStream* st)             { _stream = st; }
 
   // Constant pool parsing
-  void parse_constant_pool_entries(ClassLoaderData* loader_data,
-                                   constantPoolHandle cp, int length, TRAPS);
+  void parse_constant_pool_entries(int length, TRAPS);
 
-  constantPoolHandle parse_constant_pool(ClassLoaderData* loader_data, TRAPS);
+  constantPoolHandle parse_constant_pool(TRAPS);
 
   // Interface parsing
-  Array<Klass*>* parse_interfaces(constantPoolHandle cp,
-                                  int length,
-                                  ClassLoaderData* loader_data,
+  Array<Klass*>* parse_interfaces(int length,
                                   Handle protection_domain,
                                   Symbol* class_name,
                                   bool* has_default_methods,
                                   TRAPS);
   void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
 
+  instanceKlassHandle parse_super_class(int super_class_index, TRAPS);
   // Field parsing
-  void parse_field_attributes(ClassLoaderData* loader_data,
-                              constantPoolHandle cp, u2 attributes_count,
+  void parse_field_attributes(u2 attributes_count,
                               bool is_static, u2 signature_index,
                               u2* constantvalue_index_addr,
                               bool* is_synthetic_addr,
                               u2* generic_signature_index_addr,
-                              AnnotationArray** field_annotations,
-                              AnnotationArray** field_type_annotations,
                               FieldAnnotationCollector* parsed_annotations,
                               TRAPS);
-  Array<u2>* parse_fields(ClassLoaderData* loader_data,
-                          Symbol* class_name,
-                          constantPoolHandle cp, bool is_interface,
+  Array<u2>* parse_fields(Symbol* class_name,
+                          bool is_interface,
                           FieldAllocationCount *fac,
-                          Array<AnnotationArray*>** fields_annotations,
-                          Array<AnnotationArray*>** fields_type_annotations,
                           u2* java_fields_count_ptr, TRAPS);
 
   void print_field_layout(Symbol* name,
@@ -195,65 +231,52 @@
                           int static_fields_end);
 
   // Method parsing
-  methodHandle parse_method(ClassLoaderData* loader_data,
-                            constantPoolHandle cp,
-                            bool is_interface,
+  methodHandle parse_method(bool is_interface,
                             AccessFlags* promoted_flags,
                             TRAPS);
-  Array<Method*>* parse_methods(ClassLoaderData* loader_data,
-                                constantPoolHandle cp,
-                                bool is_interface,
+  Array<Method*>* parse_methods(bool is_interface,
                                 AccessFlags* promoted_flags,
                                 bool* has_final_method,
                                 bool* has_default_method,
                                 TRAPS);
-  Array<int>* sort_methods(ClassLoaderData* loader_data,
-                           Array<Method*>* methods,
-                           TRAPS);
-  u2* parse_exception_table(ClassLoaderData* loader_data,
-                            u4 code_length, u4 exception_table_length,
-                            constantPoolHandle cp, TRAPS);
+  intArray* sort_methods(Array<Method*>* methods);
+
+  u2* parse_exception_table(u4 code_length, u4 exception_table_length,
+                            TRAPS);
   void parse_linenumber_table(
       u4 code_attribute_length, u4 code_length,
       CompressedLineNumberWriteStream** write_stream, TRAPS);
   u2* parse_localvariable_table(u4 code_length, u2 max_locals, u4 code_attribute_length,
-                                constantPoolHandle cp, u2* localvariable_table_length,
+                                u2* localvariable_table_length,
                                 bool isLVTT, TRAPS);
   u2* parse_checked_exceptions(u2* checked_exceptions_length, u4 method_attribute_length,
-                               constantPoolHandle cp, TRAPS);
+                               TRAPS);
   void parse_type_array(u2 array_length, u4 code_length, u4* u1_index, u4* u2_index,
-                        u1* u1_array, u2* u2_array, constantPoolHandle cp, TRAPS);
-  Array<u1>* parse_stackmap_table(ClassLoaderData* loader_data, u4 code_attribute_length, TRAPS);
+                        u1* u1_array, u2* u2_array, TRAPS);
+  u1* parse_stackmap_table(u4 code_attribute_length, TRAPS);
 
   // Classfile attribute parsing
-  void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS);
-  void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
-                                                        int length, TRAPS);
-  u2   parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data,
-                                               u1* inner_classes_attribute_start,
+  void parse_classfile_sourcefile_attribute(TRAPS);
+  void parse_classfile_source_debug_extension_attribute(int length, TRAPS);
+  u2   parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
                                                bool parsed_enclosingmethod_attribute,
                                                u2 enclosing_method_class_index,
                                                u2 enclosing_method_method_index,
-                                               constantPoolHandle cp,
                                                TRAPS);
-  void parse_classfile_attributes(ClassLoaderData* loader_data,
-                                  constantPoolHandle cp,
-                                  ClassAnnotationCollector* parsed_annotations,
+  void parse_classfile_attributes(ClassAnnotationCollector* parsed_annotations,
                                   TRAPS);
-  void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS);
-  void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS);
-  void parse_classfile_bootstrap_methods_attribute(ClassLoaderData* loader_data, constantPoolHandle cp, u4 attribute_length, TRAPS);
+  void parse_classfile_synthetic_attribute(TRAPS);
+  void parse_classfile_signature_attribute(TRAPS);
+  void parse_classfile_bootstrap_methods_attribute(u4 attribute_length, TRAPS);
 
   // Annotations handling
-  AnnotationArray* assemble_annotations(ClassLoaderData* loader_data,
-                                        u1* runtime_visible_annotations,
+  AnnotationArray* assemble_annotations(u1* runtime_visible_annotations,
                                         int runtime_visible_annotations_length,
                                         u1* runtime_invisible_annotations,
                                         int runtime_invisible_annotations_length, TRAPS);
   int skip_annotation(u1* buffer, int limit, int index);
   int skip_annotation_value(u1* buffer, int limit, int index);
-  void parse_annotations(ClassLoaderData* loader_data,
-                         u1* buffer, int limit, constantPoolHandle cp,
+  void parse_annotations(u1* buffer, int limit,
                          /* Results (currently, only one result is supported): */
                          AnnotationCollector* result,
                          TRAPS);
@@ -267,8 +290,7 @@
                      int* nonstatic_oop_offsets,
                      unsigned int* nonstatic_oop_counts);
   void set_precomputed_flags(instanceKlassHandle k);
-  Array<Klass*>* compute_transitive_interfaces(ClassLoaderData* loader_data,
-                                               instanceKlassHandle super,
+  Array<Klass*>* compute_transitive_interfaces(instanceKlassHandle super,
                                                Array<Klass*>* local_ifs, TRAPS);
 
   // Format checker methods
@@ -318,7 +340,7 @@
   bool is_supported_version(u2 major, u2 minor);
   bool has_illegal_visibility(jint flags);
 
-  void verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS);
+  void verify_constantvalue(int constantvalue_index, int signature_index, TRAPS);
   void verify_legal_utf8(const unsigned char* buffer, int length, TRAPS);
   void verify_legal_class_name(Symbol* name, TRAPS);
   void verify_legal_field_name(Symbol* name, TRAPS);
@@ -359,10 +381,17 @@
   // In older versions of the VM, Klass*s cannot sneak into early phases of
   // constant pool construction, but in later versions they can.
   // %%% Let's phase out the old is_klass_reference.
-  bool is_klass_reference(constantPoolHandle cp, int index) {
-    return (EnableInvokeDynamic
-            ? cp->tag_at(index).is_klass_or_reference()
-            : cp->tag_at(index).is_klass_reference());
+  bool valid_klass_reference_at(int index) {
+    return _cp->is_within_bounds(index) &&
+         (EnableInvokeDynamic
+            ? _cp->tag_at(index).is_klass_or_reference()
+            : _cp->tag_at(index).is_klass_reference());
+  }
+
+  // Checks that the cpool index is in range and is a utf8
+  bool valid_symbol_at(int cpool_index) {
+    return (_cp->is_within_bounds(cpool_index) &&
+            _cp->tag_at(cpool_index).is_utf8());
   }
 
   void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
@@ -373,8 +402,7 @@
                                 u2** localvariable_type_table_start,
                                 TRAPS);
 
-  void copy_method_annotations(ClassLoaderData* loader_data,
-                               ConstMethod* cm,
+  void copy_method_annotations(ConstMethod* cm,
                                u1* runtime_visible_annotations,
                                int runtime_visible_annotations_length,
                                u1* runtime_invisible_annotations,
@@ -391,9 +419,15 @@
                                int annotation_default_length,
                                TRAPS);
 
+  // lays out fields in class and returns the total oopmap count
+  void layout_fields(Handle class_loader, FieldAllocationCount* fac,
+                     ClassAnnotationCollector* parsed_annotations,
+                     FieldLayoutInfo* info, TRAPS);
+
  public:
   // Constructor
   ClassFileParser(ClassFileStream* st) { set_stream(st); }
+  ~ClassFileParser();
 
   // Parse .class file and return new Klass*. The Klass* is not hooked up
   // to the system dictionary or any other structures, so a .class file can
--- a/src/share/vm/classfile/classLoaderData.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/classLoaderData.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -70,15 +70,19 @@
   _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially
   _metaspace(NULL), _unloading(false), _klasses(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
-  _next(NULL), _dependencies(NULL),
+  _next(NULL), _dependencies(),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
     // empty
 }
 
 void ClassLoaderData::init_dependencies(TRAPS) {
+  _dependencies.init(CHECK);
+}
+
+void ClassLoaderData::Dependencies::init(TRAPS) {
   // Create empty dependencies array to add to. CMS requires this to be
   // an oop so that it can track additions via card marks.  We think.
-  _dependencies = (oop)oopFactory::new_objectArray(2, CHECK);
+  _list_head = oopFactory::new_objectArray(2, CHECK);
 }
 
 bool ClassLoaderData::claim() {
@@ -95,16 +99,21 @@
   }
 
   f->do_oop(&_class_loader);
-  f->do_oop(&_dependencies);
+  _dependencies.oops_do(f);
   _handles->oops_do(f);
   if (klass_closure != NULL) {
     classes_do(klass_closure);
   }
 }
 
+void ClassLoaderData::Dependencies::oops_do(OopClosure* f) {
+  f->do_oop((oop*)&_list_head);
+}
+
 void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
     klass_closure->do_klass(k);
+    assert(k != k->next_link(), "no loops!");
   }
 }
 
@@ -113,6 +122,7 @@
     if (k->oop_is_instance()) {
       f(InstanceKlass::cast(k));
     }
+    assert(k != k->next_link(), "no loops!");
   }
 }
 
@@ -152,14 +162,14 @@
   // It's a dependency we won't find through GC, add it. This is relatively rare
   // Must handle over GC point.
   Handle dependency(THREAD, to);
-  from_cld->add_dependency(dependency, CHECK);
+  from_cld->_dependencies.add(dependency, CHECK);
 }
 
 
-void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
+void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) {
   // Check first if this dependency is already in the list.
   // Save a pointer to the last to add to under the lock.
-  objArrayOop ok = (objArrayOop)_dependencies;
+  objArrayOop ok = _list_head;
   objArrayOop last = NULL;
   while (ok != NULL) {
     last = ok;
@@ -182,16 +192,17 @@
   objArrayHandle new_dependency(THREAD, deps);
 
   // Add the dependency under lock
-  locked_add_dependency(last_handle, new_dependency);
+  locked_add(last_handle, new_dependency, THREAD);
 }
 
-void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle,
-                                            objArrayHandle new_dependency) {
+void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle,
+                                               objArrayHandle new_dependency,
+                                               Thread* THREAD) {
 
   // Have to lock and put the new dependency on the end of the dependency
   // array so the card mark for CMS sees that this dependency is new.
   // Can probably do this lock free with some effort.
-  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+  ObjectLocker ol(Handle(THREAD, _list_head), THREAD);
 
   oop loader_or_mirror = new_dependency->obj_at(0);
 
@@ -258,6 +269,7 @@
       return;
     }
     prev = k;
+    assert(k != k->next_link(), "no loops!");
   }
   ShouldNotReachHere();   // should have found this class!!
 }
@@ -318,6 +330,13 @@
   }
 }
 
+/**
+ * Returns true if this class loader data is for the extension class loader.
+ */
+bool ClassLoaderData::is_ext_class_loader_data() const {
+  return SystemDictionary::is_ext_class_loader(class_loader());
+}
+
 Metaspace* ClassLoaderData::metaspace_non_null() {
   assert(!DumpSharedSpaces, "wrong metaspace!");
   // If the metaspace has not been allocated, create a new one.  Might want
@@ -439,6 +458,7 @@
     while (k != NULL) {
       out->print_cr("klass "PTR_FORMAT", %s, CT: %d, MUT: %d", k, k->name()->as_C_string(),
           k->has_modified_oops(), k->has_accumulated_modified_oops());
+      assert(k != k->next_link(), "no loops!");
       k = k->next_link();
     }
   }
@@ -465,6 +485,7 @@
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
     guarantee(k->class_loader_data() == this, "Must be the same");
     k->verify();
+    assert(k != k->next_link(), "no loops!");
   }
 }
 
--- a/src/share/vm/classfile/classLoaderData.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/classLoaderData.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -93,6 +93,18 @@
 class ClassLoaderData : public CHeapObj<mtClass> {
   friend class VMStructs;
  private:
+  class Dependencies VALUE_OBJ_CLASS_SPEC {
+    objArrayOop _list_head;
+    void locked_add(objArrayHandle last,
+                    objArrayHandle new_dependency,
+                    Thread* THREAD);
+   public:
+    Dependencies() : _list_head(NULL) {}
+    void add(Handle dependency, TRAPS);
+    void init(TRAPS);
+    void oops_do(OopClosure* f);
+  };
+
   friend class ClassLoaderDataGraph;
   friend class ClassLoaderDataGraphMetaspaceIterator;
   friend class MetaDataFactory;
@@ -100,10 +112,11 @@
 
   static ClassLoaderData * _the_null_class_loader_data;
 
-  oop _class_loader;       // oop used to uniquely identify a class loader
-                           // class loader or a canonical class path
-  oop _dependencies;       // oop to hold dependencies from this class loader
-                           // data to others.
+  oop _class_loader;          // oop used to uniquely identify a class loader
+                              // class loader or a canonical class path
+  Dependencies _dependencies; // holds dependencies from this class loader
+                              // data to others.
+
   Metaspace * _metaspace;  // Meta-space where meta-data defined by the
                            // classes in the class loader are allocated.
   Mutex* _metaspace_lock;  // Locks the metaspace for allocations and setup.
@@ -134,9 +147,6 @@
   static Metaspace* _ro_metaspace;
   static Metaspace* _rw_metaspace;
 
-  void add_dependency(Handle dependency, TRAPS);
-  void locked_add_dependency(objArrayHandle last, objArrayHandle new_dependency);
-
   void set_next(ClassLoaderData* next) { _next = next; }
   ClassLoaderData* next() const        { return _next; }
 
@@ -191,6 +201,7 @@
   bool is_the_null_class_loader_data() const {
     return this == _the_null_class_loader_data;
   }
+  bool is_ext_class_loader_data() const;
 
   // The Metaspace is created lazily so may be NULL.  This
   // method will allocate a Metaspace if needed.
@@ -234,6 +245,7 @@
   void add_to_deallocate_list(Metadata* m);
 
   static ClassLoaderData* class_loader_data(oop loader);
+  static ClassLoaderData* class_loader_data_or_null(oop loader);
   static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS);
   static void print_loader(ClassLoaderData *loader_data, outputStream *out);
 
--- a/src/share/vm/classfile/classLoaderData.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/classLoaderData.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,9 +25,15 @@
 #include "classfile/classLoaderData.hpp"
 #include "classfile/javaClasses.hpp"
 
+inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
+  if (loader == NULL) {
+    return ClassLoaderData::the_null_class_loader_data();
+  }
+  return java_lang_ClassLoader::loader_data(loader);
+}
+
 inline ClassLoaderData* ClassLoaderData::class_loader_data(oop loader) {
-  if (loader == NULL) return ClassLoaderData::the_null_class_loader_data();
-  ClassLoaderData* loader_data = java_lang_ClassLoader::loader_data(loader);
+  ClassLoaderData* loader_data = class_loader_data_or_null(loader);
   assert(loader_data != NULL, "Must be");
   return loader_data;
 }
--- a/src/share/vm/classfile/defaultMethods.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/defaultMethods.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -348,7 +348,7 @@
 
   void disqualify_method(Method* method) {
     int* index = _member_index.get(method);
-    assert(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
+    guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
     _members.at(*index).second = DISQUALIFIED;
   }
 
--- a/src/share/vm/classfile/dictionary.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/dictionary.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -347,6 +347,7 @@
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert(obj() != NULL, "adding NULL obj");
   assert(obj()->name() == class_name, "sanity check on name");
+  assert(loader_data != NULL, "Must be non-NULL");
 
   unsigned int hash = compute_hash(class_name, loader_data);
   int index = hash_to_index(hash);
--- a/src/share/vm/classfile/javaClasses.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/javaClasses.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1060,15 +1060,16 @@
 
   // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
   enum {
-    MN_IS_METHOD           = 0x00010000, // method (not constructor)
-    MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
-    MN_IS_FIELD            = 0x00040000, // field
-    MN_IS_TYPE             = 0x00080000, // nested type
+    MN_IS_METHOD            = 0x00010000, // method (not constructor)
+    MN_IS_CONSTRUCTOR       = 0x00020000, // constructor
+    MN_IS_FIELD             = 0x00040000, // field
+    MN_IS_TYPE              = 0x00080000, // nested type
+    MN_CALLER_SENSITIVE     = 0x00100000, // @CallerSensitive annotation detected
     MN_REFERENCE_KIND_SHIFT = 24, // refKind
-    MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
+    MN_REFERENCE_KIND_MASK  = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
     // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
-    MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes
-    MN_SEARCH_INTERFACES   = 0x00200000  // walk implemented interfaces
+    MN_SEARCH_SUPERCLASSES  = 0x00100000, // walk super classes
+    MN_SEARCH_INTERFACES    = 0x00200000  // walk implemented interfaces
   };
 
   // Accessors for code generation:
--- a/src/share/vm/classfile/symbolTable.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/symbolTable.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -49,18 +49,17 @@
 
   Symbol* sym;
 
-  if (c_heap) {
+  if (DumpSharedSpaces) {
+    // Allocate all symbols to CLD shared metaspace
+    sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1);
+  } else if (c_heap) {
     // refcount starts as 1
-    assert(!DumpSharedSpaces, "never allocate to C heap");
     sym = new (len, THREAD) Symbol(name, len, 1);
     assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
   } else {
-    if (DumpSharedSpaces) {
-      sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1);
-  } else {
+    // Allocate to global arena
     sym = new (len, arena(), THREAD) Symbol(name, len, -1);
   }
-  }
   return sym;
 }
 
@@ -678,9 +677,14 @@
   ResourceMark rm;
   int length;
   jchar* chars = symbol->as_unicode(length);
-  unsigned int hashValue = hash_string(chars, length);
-  int index = the_table()->hash_to_index(hashValue);
-  return the_table()->lookup(index, chars, length, hashValue);
+  return lookup(chars, length);
+}
+
+
+oop StringTable::lookup(jchar* name, int len) {
+  unsigned int hash = hash_string(name, len);
+  int index = the_table()->hash_to_index(hash);
+  return the_table()->lookup(index, name, len, hash);
 }
 
 
--- a/src/share/vm/classfile/symbolTable.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/symbolTable.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -287,6 +287,7 @@
 
   // Probing
   static oop lookup(Symbol* symbol);
+  static oop lookup(jchar* chars, int length);
 
   // Interning
   static oop intern(Symbol* symbol, TRAPS);
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -146,6 +146,17 @@
    }
    return false;
 }
+
+/**
+ * Returns true if the passed class loader is the extension class loader.
+ */
+bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
+  if (class_loader.is_null()) {
+    return false;
+  }
+  return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
+}
+
 // ----------------------------------------------------------------------------
 // Resolving of classes
 
@@ -804,6 +815,47 @@
       }
     } // load_instance_class loop
 
+    if (HAS_PENDING_EXCEPTION) {
+      // An exception, such as OOM could have happened at various places inside
+      // load_instance_class. We might have partially initialized a shared class
+      // and need to clean it up.
+      if (class_loader.is_null()) {
+        // In some cases k may be null. Let's find the shared class again.
+        instanceKlassHandle ik(THREAD, find_shared_class(name));
+        if (ik.not_null()) {
+          if (ik->class_loader_data() == NULL) {
+            // We didn't go as far as Klass::restore_unshareable_info(),
+            // so nothing to clean up.
+          } else {
+            Klass *kk;
+            {
+              MutexLocker mu(SystemDictionary_lock, THREAD);
+              kk = find_class(name, ik->class_loader_data());
+            }
+            if (kk != NULL) {
+              // No clean up is needed if the shared class has been entered
+              // into system dictionary, as load_shared_class() won't be called
+              // again.
+            } else {
+              // This must be done outside of the SystemDictionary_lock to
+              // avoid deadlock.
+              //
+              // Note that Klass::restore_unshareable_info (called via
+              // load_instance_class above) is also called outside
+              // of SystemDictionary_lock. Other threads are blocked from
+              // loading this class because they are waiting on the
+              // SystemDictionary_lock until this thread removes
+              // the placeholder below.
+              //
+              // This need to be re-thought when parallel-capable non-boot
+              // classloaders are supported by CDS (today they're not).
+              clean_up_shared_class(ik, class_loader, THREAD);
+            }
+          }
+        }
+      }
+    }
+
     if (load_instance_added == true) {
       // clean up placeholder entries for LOAD_INSTANCE success or error
       // This brackets the SystemDictionary updates for both defining
@@ -866,16 +918,22 @@
 // the new entry.
 
 Klass* SystemDictionary::find(Symbol* class_name,
-                                Handle class_loader,
-                                Handle protection_domain,
-                                TRAPS) {
+                              Handle class_loader,
+                              Handle protection_domain,
+                              TRAPS) {
 
   // UseNewReflection
   // The result of this call should be consistent with the result
   // of the call to resolve_instance_class_or_null().
   // See evaluation 6790209 and 4474172 for more details.
   class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
-  ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL);
+  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader());
+
+  if (loader_data == NULL) {
+    // If the ClassLoaderData has not been setup,
+    // then the class loader has no entries in the dictionary.
+    return NULL;
+  }
 
   unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
   int d_index = dictionary()->hash_to_index(d_hash);
@@ -1134,11 +1192,6 @@
   return load_shared_class(ik, class_loader, THREAD);
 }
 
-// Note well!  Changes to this method may affect oop access order
-// in the shared archive.  Please take care to not make changes that
-// adversely affect cold start time by changing the oop access order
-// that is specified in dump.cpp MarkAndMoveOrderedReadOnly and
-// MarkAndMoveOrderedReadWrite closures.
 instanceKlassHandle SystemDictionary::load_shared_class(
                  instanceKlassHandle ik, Handle class_loader, TRAPS) {
   assert(class_loader.is_null(), "non-null classloader for shared class?");
@@ -1199,6 +1252,19 @@
   return ik;
 }
 
+void SystemDictionary::clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS) {
+  // Updating methods must be done under a lock so multiple
+  // threads don't update these in parallel
+  // Shared classes are all currently loaded by the bootstrap
+  // classloader, so this will never cause a deadlock on
+  // a custom class loader lock.
+  {
+    Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
+    check_loader_lock_contention(lockObject, THREAD);
+    ObjectLocker ol(lockObject, THREAD, true);
+    ik->remove_unshareable_info();
+  }
+}
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
@@ -1526,9 +1592,10 @@
 // Used for assertions and verification only
 Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
   #ifndef ASSERT
-  guarantee(VerifyBeforeGC   ||
-            VerifyDuringGC   ||
-            VerifyBeforeExit ||
+  guarantee(VerifyBeforeGC      ||
+            VerifyDuringGC      ||
+            VerifyBeforeExit    ||
+            VerifyDuringStartup ||
             VerifyAfterGC, "too expensive");
   #endif
   assert_locked_or_safepoint(SystemDictionary_lock);
@@ -2145,10 +2212,9 @@
 // Make sure all class components (including arrays) in the given
 // signature will be resolved to the same class in both loaders.
 // Returns the name of the type that failed a loader constraint check, or
-// NULL if no constraint failed. The returned C string needs cleaning up
-// with a ResourceMark in the caller.  No exception except OOME is thrown.
+// NULL if no constraint failed.  No exception except OOME is thrown.
 // Arrays are not added to the loader constraint table, their elements are.
-char* SystemDictionary::check_signature_loaders(Symbol* signature,
+Symbol* SystemDictionary::check_signature_loaders(Symbol* signature,
                                                Handle loader1, Handle loader2,
                                                bool is_method, TRAPS)  {
   // Nothing to do if loaders are the same.
@@ -2156,14 +2222,12 @@
     return NULL;
   }
 
-  ResourceMark rm(THREAD);
   SignatureStream sig_strm(signature, is_method);
   while (!sig_strm.is_done()) {
     if (sig_strm.is_object()) {
-      Symbol* s = sig_strm.as_symbol(CHECK_NULL);
-      Symbol*  sig  = s;
+      Symbol* sig = sig_strm.as_symbol(CHECK_NULL);
       if (!add_loader_constraint(sig, loader1, loader2, THREAD)) {
-        return sig->as_C_string();
+        return sig;
       }
     }
     sig_strm.next();
--- a/src/share/vm/classfile/systemDictionary.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -106,6 +106,7 @@
   do_klass(ThreadDeath_klass,                           java_lang_ThreadDeath,                     Pre                 ) \
   do_klass(Exception_klass,                             java_lang_Exception,                       Pre                 ) \
   do_klass(RuntimeException_klass,                      java_lang_RuntimeException,                Pre                 ) \
+  do_klass(SecurityManager_klass,                       java_lang_SecurityManager,                 Pre                 ) \
   do_klass(ProtectionDomain_klass,                      java_security_ProtectionDomain,            Pre                 ) \
   do_klass(AccessControlContext_klass,                  java_security_AccessControlContext,        Pre                 ) \
   do_klass(ClassNotFoundException_klass,                java_lang_ClassNotFoundException,          Pre                 ) \
@@ -138,13 +139,14 @@
   /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */                              \
   /* Universe::is_gte_jdk14x_version() is not set up by this point. */                                                   \
   /* It's okay if this turns out to be NULL in non-1.4 JDKs. */                                                          \
-  do_klass(lambda_MagicLambdaImpl_klass,                java_lang_invoke_MagicLambdaImpl, Opt ) \
+  do_klass(lambda_MagicLambdaImpl_klass,                java_lang_invoke_MagicLambdaImpl,          Opt                 ) \
   do_klass(reflect_MagicAccessorImpl_klass,             sun_reflect_MagicAccessorImpl,             Opt                 ) \
   do_klass(reflect_MethodAccessorImpl_klass,            sun_reflect_MethodAccessorImpl,            Opt_Only_JDK14NewRef) \
   do_klass(reflect_ConstructorAccessorImpl_klass,       sun_reflect_ConstructorAccessorImpl,       Opt_Only_JDK14NewRef) \
   do_klass(reflect_DelegatingClassLoader_klass,         sun_reflect_DelegatingClassLoader,         Opt                 ) \
   do_klass(reflect_ConstantPool_klass,                  sun_reflect_ConstantPool,                  Opt_Only_JDK15      ) \
   do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15      ) \
+  do_klass(reflect_CallerSensitive_klass,               sun_reflect_CallerSensitive,               Opt                 ) \
                                                                                                                          \
   /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */                                            \
   do_klass(MethodHandle_klass,                          java_lang_invoke_MethodHandle,             Pre_JSR292          ) \
@@ -197,8 +199,10 @@
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
+  do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Opt) \
   do_klass(Assumptions_ConcreteSubtype_klass,     com_oracle_graal_api_code_Assumptions_ConcreteSubtype,        Opt) \
   do_klass(Assumptions_MethodContents_klass,      com_oracle_graal_api_code_Assumptions_MethodContents,         Opt) \
+  do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
   do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Opt) \
   do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Opt) \
   do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Opt) \
@@ -207,8 +211,9 @@
   do_klass(CompilationResult_DataPatch_klass,     com_oracle_graal_api_code_CompilationResult_DataPatch,        Opt) \
   do_klass(CompilationResult_ExceptionHandler_klass, com_oracle_graal_api_code_CompilationResult_ExceptionHandler, Opt) \
   do_klass(CompilationResult_Mark_klass,          com_oracle_graal_api_code_CompilationResult_Mark,             Opt) \
-  do_klass(CompilationResult_Safepoint_klass,     com_oracle_graal_api_code_CompilationResult_Safepoint,        Opt) \
+  do_klass(CompilationResult_Infopoint_klass,     com_oracle_graal_api_code_CompilationResult_Infopoint,        Opt) \
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
+  do_klass(InfopointReason_klass,                 com_oracle_graal_api_code_InfopointReason,                    Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
@@ -525,8 +530,8 @@
   // Check class loader constraints
   static bool add_loader_constraint(Symbol* name, Handle loader1,
                                     Handle loader2, TRAPS);
-  static char* check_signature_loaders(Symbol* signature, Handle loader1,
-                                       Handle loader2, bool is_method, TRAPS);
+  static Symbol* check_signature_loaders(Symbol* signature, Handle loader1,
+                                         Handle loader2, bool is_method, TRAPS);
 
   // JSR 292
   // find a java.lang.invoke.MethodHandle.invoke* method for a given signature
@@ -663,18 +668,22 @@
                                                Handle class_loader, TRAPS);
   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
                                                Handle class_loader, TRAPS);
+  static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS);
   static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
   static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
   static void check_loader_lock_contention(Handle loader_lock, TRAPS);
   static bool is_parallelCapable(Handle class_loader);
   static bool is_parallelDefine(Handle class_loader);
 
+public:
+  static bool is_ext_class_loader(Handle class_loader);
+
+private:
   static Klass* find_shared_class(Symbol* class_name);
 
   // Setup link to hierarchy
   static void add_to_hierarchy(instanceKlassHandle k, TRAPS);
 
-private:
   // We pass in the hashtable index so we can calculate it outside of
   // the SystemDictionary_lock.
 
--- a/src/share/vm/classfile/verifier.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/verifier.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -61,8 +61,9 @@
 # include "bytes_ppc.hpp"
 #endif
 
-#define NOFAILOVER_MAJOR_VERSION                  51
-#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION  52
+#define NOFAILOVER_MAJOR_VERSION                       51
+#define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION  51
+#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION       52
 
 // Access to external entry for VerifyClassCodes - old byte code verifier
 
@@ -127,8 +128,7 @@
     if (TraceClassInitialization) {
       tty->print_cr("Start class verification for: %s", klassName);
     }
-    if (UseSplitVerifier &&
-        klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
+    if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
       ClassVerifier split_verifier(klass, THREAD);
       split_verifier.verify_class(THREAD);
       exception_name = split_verifier.result();
@@ -2027,16 +2027,19 @@
   address bcp = bcs->bcp();
   address aligned_bcp = (address) round_to((intptr_t)(bcp + 1), jintSize);
 
-  // 4639449 & 4647081: padding bytes must be 0
-  u2 padding_offset = 1;
-  while ((bcp + padding_offset) < aligned_bcp) {
-    if(*(bcp + padding_offset) != 0) {
-      verify_error(ErrorContext::bad_code(bci),
-                   "Nonzero padding byte in lookswitch or tableswitch");
-      return;
+  if (_klass->major_version() < NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION) {
+    // 4639449 & 4647081: padding bytes must be 0
+    u2 padding_offset = 1;
+    while ((bcp + padding_offset) < aligned_bcp) {
+      if(*(bcp + padding_offset) != 0) {
+        verify_error(ErrorContext::bad_code(bci),
+                     "Nonzero padding byte in lookswitch or tableswitch");
+        return;
+      }
+      padding_offset++;
     }
-    padding_offset++;
   }
+
   int default_offset = (int) Bytes::get_Java_u4(aligned_bcp);
   int keys, delta;
   current_frame->pop_stack(
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -91,6 +91,7 @@
   template(java_lang_StringBuffer,                    "java/lang/StringBuffer")                   \
   template(java_lang_StringBuilder,                   "java/lang/StringBuilder")                  \
   template(java_lang_CharSequence,                    "java/lang/CharSequence")                   \
+  template(java_lang_SecurityManager,                 "java/lang/SecurityManager")                \
   template(java_security_AccessControlContext,        "java/security/AccessControlContext")       \
   template(java_security_ProtectionDomain,            "java/security/ProtectionDomain")           \
   template(java_io_OutputStream,                      "java/io/OutputStream")                     \
@@ -211,6 +212,8 @@
   template(sun_reflect_SerializationConstructorAccessorImpl, "sun/reflect/SerializationConstructorAccessorImpl") \
   template(sun_reflect_DelegatingClassLoader,         "sun/reflect/DelegatingClassLoader")        \
   template(sun_reflect_Reflection,                    "sun/reflect/Reflection")                   \
+  template(sun_reflect_CallerSensitive,               "sun/reflect/CallerSensitive")              \
+  template(sun_reflect_CallerSensitive_signature,     "Lsun/reflect/CallerSensitive;")            \
   template(checkedExceptions_name,                    "checkedExceptions")                        \
   template(clazz_name,                                "clazz")                                    \
   template(exceptionTypes_name,                       "exceptionTypes")                           \
@@ -296,6 +299,7 @@
   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_bridge_CompilerToVMImpl,         "com/oracle/graal/hotspot/bridge/CompilerToVMImpl")              \
   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")            \
   template(com_oracle_graal_hotspot_meta_HotSpotJavaType,            "com/oracle/graal/hotspot/meta/HotSpotJavaType")                 \
@@ -319,14 +323,17 @@
   template(com_oracle_graal_api_code_Assumptions,                    "com/oracle/graal/api/code/Assumptions")                         \
   template(com_oracle_graal_api_code_Assumptions_MethodContents,     "com/oracle/graal/api/code/Assumptions$MethodContents")          \
   template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")         \
+  template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass") \
   template(com_oracle_graal_api_code_Assumptions_ConcreteMethod,     "com/oracle/graal/api/code/Assumptions$ConcreteMethod")          \
+  template(com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/code/Assumptions$CallSiteTargetValue")     \
   template(com_oracle_graal_api_code_CompilationResult,              "com/oracle/graal/api/code/CompilationResult")                   \
   template(com_oracle_graal_api_code_CompilationResult_Call,         "com/oracle/graal/api/code/CompilationResult$Call")              \
   template(com_oracle_graal_api_code_CompilationResult_DataPatch,    "com/oracle/graal/api/code/CompilationResult$DataPatch")         \
   template(com_oracle_graal_api_code_CompilationResult_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \
   template(com_oracle_graal_api_code_CompilationResult_Mark,         "com/oracle/graal/api/code/CompilationResult$Mark")              \
-  template(com_oracle_graal_api_code_CompilationResult_Safepoint,    "com/oracle/graal/api/code/CompilationResult$Safepoint")         \
+  template(com_oracle_graal_api_code_CompilationResult_Infopoint,    "com/oracle/graal/api/code/CompilationResult$Infopoint")         \
   template(com_oracle_graal_api_code_CompilationResult_Site,         "com/oracle/graal/api/code/CompilationResult$Site")              \
+  template(com_oracle_graal_api_code_InfopointReason,                "com/oracle/graal/api/code/InfopointReason")                     \
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
@@ -334,6 +341,7 @@
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
+  template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(shutdownCompiler_name,                 "shutdownCompiler")                                                                 \
@@ -374,7 +382,6 @@
   template(forObject_name,                        "forObject")                                                                        \
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
   template(callback_signature,                    "(Ljava/lang/Object;)Ljava/lang/Object;")                                           \
-  template(MethodInvalidatedException,            "com/oracle/graal/api/code/InstalledCode$MethodInvalidatedException")               \
   /* graal.api.interpreter */                                                                                                         \
   template(com_oracle_graal_api_interpreter_Interpreter,             "com/oracle/graal/api/interpreter/Interpreter")                  \
   template(interpreter_execute_name,              "execute")                                                                          \
@@ -438,6 +445,7 @@
   template(contextClassLoader_name,                   "contextClassLoader")                       \
   template(inheritedAccessControlContext_name,        "inheritedAccessControlContext")            \
   template(isPrivileged_name,                         "isPrivileged")                             \
+  template(getClassContext_name,                      "getClassContext")                          \
   template(wait_name,                                 "wait")                                     \
   template(checkPackageAccess_name,                   "checkPackageAccess")                       \
   template(stackSize_name,                            "stackSize")                                \
@@ -561,6 +569,7 @@
   template(void_classloader_signature,                "()Ljava/lang/ClassLoader;")                                \
   template(void_object_signature,                     "()Ljava/lang/Object;")                                     \
   template(void_class_signature,                      "()Ljava/lang/Class;")                                      \
+  template(void_class_array_signature,                "()[Ljava/lang/Class;")                                     \
   template(void_string_signature,                     "()Ljava/lang/String;")                                     \
   template(object_array_object_signature,             "([Ljava/lang/Object;)Ljava/lang/Object;")                  \
   template(object_object_array_object_signature,      "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
@@ -803,9 +812,8 @@
   do_intrinsic(_getLength,                java_lang_reflect_Array, getLength_name, object_int_signature,         F_SN)  \
    do_name(     getLength_name,                                   "getLength")                                          \
                                                                                                                         \
-  do_intrinsic(_getCallerClass,           sun_reflect_Reflection, getCallerClass_name, getCallerClass_signature, F_SN)  \
+  do_intrinsic(_getCallerClass,           sun_reflect_Reflection, getCallerClass_name, void_class_signature,     F_SN)  \
    do_name(     getCallerClass_name,                             "getCallerClass")                                      \
-   do_signature(getCallerClass_signature,                        "(I)Ljava/lang/Class;")                                \
                                                                                                                         \
   do_intrinsic(_newArray,                 java_lang_reflect_Array, newArray_name, newArray_signature,            F_SN)  \
    do_name(     newArray_name,                                    "newArray")                                           \
@@ -1122,6 +1130,9 @@
   do_intrinsic(_Double_valueOf,           java_lang_Double,       valueOf_name, Double_valueOf_signature, F_S)          \
    do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")                               \
                                                                                                                         \
+  do_intrinsic(_CompilerToVMImpl_executeCompiledMethod,           com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\
+   do_name(     CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;")                               \
+   do_name(     executeCompiledMethod_name,                       "executeCompiledMethodIntrinsic")                     \
     /*end*/
 
 
--- a/src/share/vm/code/codeBlob.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/codeBlob.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -186,7 +186,7 @@
     FREE_C_HEAP_ARRAY(unsigned char, _oop_maps, mtCode);
     _oop_maps = NULL;
   }
-  _comments.free();
+  _strings.free();
 }
 
 
--- a/src/share/vm/code/codeBlob.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/codeBlob.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -66,7 +66,7 @@
   int        _data_offset;                       // offset to where data region begins
   int        _frame_size;                        // size of stack frame
   OopMapSet* _oop_maps;                          // OopMap for this CodeBlob
-  CodeComments _comments;
+  CodeStrings _strings;
 
  public:
   // Returns the space needed for CodeBlob
@@ -187,12 +187,12 @@
   // Print the comment associated with offset on stream, if there is one
   virtual void print_block_comment(outputStream* stream, address block_begin) const {
     intptr_t offset = (intptr_t)(block_begin - code_begin());
-    _comments.print_block_comment(stream, offset);
+    _strings.print_block_comment(stream, offset);
   }
 
   // Transfer ownership of comments to this CodeBlob
-  void set_comments(CodeComments& comments) {
-    _comments.assign(comments);
+  void set_strings(CodeStrings& strings) {
+    _strings.assign(strings);
   }
 };
 
@@ -358,10 +358,11 @@
 
   int _unpack_with_exception_in_tls;
 
+#ifdef GRAAL
   // (thomaswue) Offset when Graal calls uncommon_trap.
   int _uncommon_trap_offset;
   int _implicit_exception_uncommon_trap_offset;
-
+#endif
 
   // Creation support
   DeoptimizationBlob(
@@ -416,6 +417,7 @@
   }
   address unpack_with_exception_in_tls() const   { return code_begin() + _unpack_with_exception_in_tls; }
 
+#ifdef GRAAL
   // (thomaswue) Offset when Graal calls uncommon_trap.
   void set_uncommon_trap_offset(int offset) {
     _uncommon_trap_offset = offset;
@@ -427,7 +429,7 @@
     assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");
   }
   address implicit_exception_uncommon_trap() const                  { return code_begin() + _implicit_exception_uncommon_trap_offset;     }
-
+#endif
 };
 
 
--- a/src/share/vm/code/codeCache.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/codeCache.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -156,6 +156,11 @@
   static address  low_bound()                    { return (address) _heap->low_boundary(); }
   static address  high_bound()                   { return (address) _heap->high_boundary(); }
 
+  static bool has_space(int size) {
+    // Always leave some room in the CodeCache for I2C/C2I adapters
+    return largest_free_block() > (CodeCacheMinimumFreeSpace + size);
+  }
+
   // Profiling
   static address first_address();                // first address used for CodeBlobs
   static address last_address();                 // last  address used for CodeBlobs
--- a/src/share/vm/code/compiledIC.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/compiledIC.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -567,7 +567,7 @@
     return;
   }
 #endif
-  assert(stub!=NULL, "stub not found");
+  guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
--- a/src/share/vm/code/compressedStream.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/compressedStream.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -195,7 +195,7 @@
 // for this block (a matching directive turns it back on later).
 // These directives can be removed once the MS VS.NET 2005
 // compiler stack overflow is fixed.
-#if _MSC_VER >=1400 && !defined(_WIN64)
+#if defined(_MSC_VER) && _MSC_VER >=1400 && !defined(_WIN64)
 #pragma optimize("", off)
 #pragma warning(disable: 4748)
 #endif
@@ -276,7 +276,7 @@
   guarantee(fails == 0, "test failures");
 }
 
-#if _MSC_VER >=1400 && !defined(_WIN64)
+#if defined(_MSC_VER) &&_MSC_VER >=1400 && !defined(_WIN64)
 #pragma warning(default: 4748)
 #pragma optimize("", on)
 #endif
--- a/src/share/vm/code/dependencies.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/dependencies.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -144,6 +144,11 @@
   assert_common_1(evol_method, DepValue(_oop_recorder, m));
 }
 
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
+  check_ctxk(ctxk);
+  assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
+}
+
 void Dependencies::assert_leaf_type(Klass* ctxk) {
   if (ctxk->oop_is_array()) {
     // As a special case, support this assertion on an array type,
@@ -170,6 +175,10 @@
   check_ctxk(ctxk);
   assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
 }
+
+void Dependencies::assert_call_site_target_value(oop call_site, oop method_handle) {
+  assert_common_2(call_site_target_value, DepValue(_oop_recorder, JNIHandles::make_local(call_site)), DepValue(_oop_recorder, JNIHandles::make_local(method_handle)));
+}
 #endif // GRAAL
 
 
--- a/src/share/vm/code/dependencies.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/dependencies.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -360,9 +360,11 @@
 
  public:
   void assert_evol_method(Method* m);
+  void assert_has_no_finalizable_subclasses(Klass* ctxk);
   void assert_leaf_type(Klass* ctxk);
   void assert_unique_concrete_method(Klass* ctxk, Method* uniqm);
   void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck);
+  void assert_call_site_target_value(oop callSite, oop methodHandle);
 #endif // GRAAL
 
   // Define whether a given method or type is concrete.
--- a/src/share/vm/code/icBuffer.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/icBuffer.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -50,7 +50,7 @@
   friend class ICStubInterface;
   // This will be called only by ICStubInterface
   void    initialize(int size,
-                     CodeComments comments)      { _size = size; _ic_site = NULL; }
+                     CodeStrings strings)        { _size = size; _ic_site = NULL; }
   void    finalize(); // called when a method is removed
 
   // General info
--- a/src/share/vm/code/nmethod.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -497,7 +497,6 @@
 #endif // def HAVE_DTRACE_H
 }
 
-
 nmethod* nmethod::new_native_nmethod(methodHandle method,
   int compile_id,
   CodeBuffer *code_buffer,
@@ -513,17 +512,19 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
-    CodeOffsets offsets;
-    offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
-    offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
-    nm = new (native_nmethod_size)
-      nmethod(method(), native_nmethod_size, compile_id, &offsets,
-              code_buffer, frame_size,
-              basic_lock_owner_sp_offset, basic_lock_sp_offset,
-              oop_maps);
-    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_native_nmethod(nm));
-    if (PrintAssembly && nm != NULL)
-      Disassembler::decode(nm);
+    if (CodeCache::has_space(native_nmethod_size)) {
+      CodeOffsets offsets;
+      offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
+      offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
+      nm = new (native_nmethod_size) nmethod(method(), native_nmethod_size,
+                                             compile_id, &offsets,
+                                             code_buffer, frame_size,
+                                             basic_lock_owner_sp_offset,
+                                             basic_lock_sp_offset, oop_maps);
+      NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_native_nmethod(nm));
+      if (PrintAssembly && nm != NULL)
+        Disassembler::decode(nm);
+    }
   }
   // verify nmethod
   debug_only(if (nm) nm->verify();) // might block
@@ -548,16 +549,19 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     int nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
-    CodeOffsets offsets;
-    offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
-    offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset);
-    offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
-
-    nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size);
-
-    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
-    if (PrintAssembly && nm != NULL)
-      Disassembler::decode(nm);
+    if (CodeCache::has_space(nmethod_size)) {
+      CodeOffsets offsets;
+      offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
+      offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset);
+      offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
+
+      nm = new (nmethod_size) nmethod(method(), nmethod_size,
+                                      &offsets, code_buffer, frame_size);
+
+      NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
+      if (PrintAssembly && nm != NULL)
+        Disassembler::decode(nm);
+    }
   }
   // verify nmethod
   debug_only(if (nm) nm->verify();) // might block
@@ -604,8 +608,9 @@
       + round_to(handler_table->size_in_bytes(), oopSize)
       + round_to(nul_chk_table->size_in_bytes(), oopSize)
       + round_to(debug_info->data_size()       , oopSize)
-      + leaf_graph_ids_size;
-    nm = new (nmethod_size)
+      + leaf_graph_ids_size;
+    if (CodeCache::has_space(nmethod_size)) {
+      nm = new (nmethod_size)
       nmethod(method(), nmethod_size, compile_id, entry_bci, offsets,
               orig_pc_offset, debug_info, dependencies, code_buffer, frame_size,
               oop_maps,
@@ -618,7 +623,8 @@
               , installed_code,
               triggered_deoptimizations
 #endif
-              );
+              );
+    }
     if (nm != NULL) {
       // To make dependency checking during class loading fast, record
       // the nmethod dependencies in the classes it is dependent on.
@@ -818,9 +824,9 @@
 #endif // def HAVE_DTRACE_H
 
 void* nmethod::operator new(size_t size, int nmethod_size) {
-  // Always leave some room in the CodeCache for I2C/C2I adapters
-  if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) return NULL;
-  return CodeCache::allocate(nmethod_size);
+  void*  alloc = CodeCache::allocate(nmethod_size);
+  guarantee(alloc != NULL, "CodeCache should have enough space");
+  return alloc;
 }
 
 
@@ -1301,10 +1307,12 @@
   }
 
 #ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
-      _graal_installed_code = NULL;
-    }
+  // The method can only be unloaded after the pointer to the installed code
+  // Java wrapper is no longer alive. Here we need to clear out this weak
+  // reference to the dead object.
+  if (_graal_installed_code != NULL) {
+    _graal_installed_code = NULL;
+  }
 #endif
 
   // Make the class unloaded - i.e., change state and notify sweeper
@@ -1388,18 +1396,17 @@
       return false;
     }
 
-#ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
-      _graal_installed_code = NULL;
-    }
-#endif
-
     // The caller can be calling the method statically or through an inline
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
-      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                  SharedRuntime::get_handle_wrong_method_stub());
+      address stub = SharedRuntime::get_handle_wrong_method_stub();
+#ifdef GRAAL
+      if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) {
+        // This was manually installed machine code. Patch entry with stub that throws an exception.
+        stub = SharedRuntime::get_deoptimized_installed_code_stub();
+      }
+#endif
+      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
     }
 
     if (is_in_use()) {
--- a/src/share/vm/code/stubs.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/stubs.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -101,8 +101,8 @@
 
 Stub* StubQueue::request_committed(int code_size) {
   Stub* s = request(code_size);
-  CodeComments comments;
-  if (s != NULL) commit(code_size, comments);
+  CodeStrings strings;
+  if (s != NULL) commit(code_size, strings);
   return s;
 }
 
@@ -119,8 +119,8 @@
       assert(_buffer_limit == _buffer_size, "buffer must be fully usable");
       if (_queue_end + requested_size <= _buffer_size) {
         // code fits in at the end => nothing to do
-        CodeComments comments;
-        stub_initialize(s, requested_size, comments);
+        CodeStrings strings;
+        stub_initialize(s, requested_size, strings);
         return s;
       } else {
         // stub doesn't fit in at the queue end
@@ -137,8 +137,8 @@
     // Queue: |XXX|.......|XXXXXXX|.......|
     //        ^0  ^end    ^begin  ^limit  ^size
     s = current_stub();
-    CodeComments comments;
-    stub_initialize(s, requested_size, comments);
+    CodeStrings strings;
+    stub_initialize(s, requested_size, strings);
     return s;
   }
   // Not enough space left
@@ -147,12 +147,12 @@
 }
 
 
-void StubQueue::commit(int committed_code_size, CodeComments& comments) {
+void StubQueue::commit(int committed_code_size, CodeStrings& strings) {
   assert(committed_code_size > 0, "committed_code_size must be > 0");
   int committed_size = round_to(stub_code_size_to_size(committed_code_size), CodeEntryAlignment);
   Stub* s = current_stub();
   assert(committed_size <= stub_size(s), "committed size must not exceed requested size");
-  stub_initialize(s, committed_size, comments);
+  stub_initialize(s, committed_size, strings);
   _queue_end += committed_size;
   _number_of_stubs++;
   if (_mutex != NULL) _mutex->unlock();
--- a/src/share/vm/code/stubs.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/code/stubs.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -73,7 +73,7 @@
  public:
   // Initialization/finalization
   void    initialize(int size,
-                     CodeComments& comments)     { ShouldNotCallThis(); }                // called to initialize/specify the stub's size
+                     CodeStrings& strings)       { ShouldNotCallThis(); }                // called to initialize/specify the stub's size
   void    finalize()                             { ShouldNotCallThis(); }                // called before the stub is deallocated
 
   // General info/converters
@@ -107,7 +107,7 @@
  public:
   // Initialization/finalization
   virtual void    initialize(Stub* self, int size,
-                             CodeComments& comments)       = 0; // called after creation (called twice if allocated via (request, commit))
+                             CodeStrings& strings)         = 0; // called after creation (called twice if allocated via (request, commit))
   virtual void    finalize(Stub* self)                     = 0; // called before deallocation
 
   // General info/converters
@@ -136,7 +136,7 @@
    public:                                                 \
     /* Initialization/finalization */                      \
     virtual void    initialize(Stub* self, int size,       \
-                               CodeComments& comments)     { cast(self)->initialize(size, comments); } \
+                               CodeStrings& strings)       { cast(self)->initialize(size, strings); } \
     virtual void    finalize(Stub* self)                   { cast(self)->finalize(); }             \
                                                            \
     /* General info */                                     \
@@ -176,7 +176,7 @@
 
   // Stub functionality accessed via interface
   void  stub_initialize(Stub* s, int size,
-                        CodeComments& comments)  { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, comments); }
+                        CodeStrings& strings)    { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, strings); }
   void  stub_finalize(Stub* s)                   { _stub_interface->finalize(s); }
   int   stub_size(Stub* s) const                 { return _stub_interface->size(s); }
   bool  stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
@@ -206,7 +206,7 @@
   Stub* request_committed(int code_size);        // request a stub that provides exactly code_size space for code
   Stub* request(int requested_code_size);        // request a stub with a (maximum) code space - locks the queue
   void  commit (int committed_code_size,
-                CodeComments& comments);         // commit the previously requested stub - unlocks the queue
+                CodeStrings& strings);           // commit the previously requested stub - unlocks the queue
 
   // Stub deallocation
   void  remove_first();                          // remove the first stub in the queue
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -68,9 +68,8 @@
 HS_DTRACE_PROBE_DECL9(hotspot, method__compile__end,
   char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t, bool);
 
-#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method)              \
+#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method, comp_name)   \
   {                                                                      \
-    char* comp_name = (char*)(compiler)->name();                         \
     Symbol* klass_name = (method)->klass_name();                         \
     Symbol* name = (method)->name();                                     \
     Symbol* signature = (method)->signature();                           \
@@ -81,9 +80,9 @@
       signature->bytes(), signature->utf8_length());                     \
   }
 
-#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, success)       \
+#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method,                \
+                                        comp_name, success)              \
   {                                                                      \
-    char* comp_name = (char*)(compiler)->name();                         \
     Symbol* klass_name = (method)->klass_name();                         \
     Symbol* name = (method)->name();                                     \
     Symbol* signature = (method)->signature();                           \
@@ -96,22 +95,21 @@
 
 #else /* USDT2 */
 
-#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method)              \
+#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method, comp_name)   \
   {                                                                      \
-    char* comp_name = (char*)(compiler)->name();                         \
     Symbol* klass_name = (method)->klass_name();                         \
     Symbol* name = (method)->name();                                     \
     Symbol* signature = (method)->signature();                           \
-    HOTSPOT_METHOD_COMPILE_BEGIN(                                       \
+    HOTSPOT_METHOD_COMPILE_BEGIN(                                        \
       comp_name, strlen(comp_name),                                      \
-      (char *) klass_name->bytes(), klass_name->utf8_length(),          \
+      (char *) klass_name->bytes(), klass_name->utf8_length(),           \
       (char *) name->bytes(), name->utf8_length(),                       \
       (char *) signature->bytes(), signature->utf8_length());            \
   }
 
-#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, success)       \
+#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method,                \
+                                        comp_name, success)              \
   {                                                                      \
-    char* comp_name = (char*)(compiler)->name();                         \
     Symbol* klass_name = (method)->klass_name();                         \
     Symbol* name = (method)->name();                                     \
     Symbol* signature = (method)->signature();                           \
@@ -125,8 +123,8 @@
 
 #else //  ndef DTRACE_ENABLED
 
-#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method)
-#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, success)
+#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method, comp_name)
+#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, comp_name, success)
 
 #endif // ndef DTRACE_ENABLED
 
@@ -362,7 +360,7 @@
 //
 void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
   // print compiler name
-  st->print("%s:", CompileBroker::compiler(comp_level())->name());
+  st->print("%s:", CompileBroker::compiler_name(comp_level()));
   print_compilation(st);
 }
 
@@ -371,7 +369,7 @@
 void CompileTask::print_line() {
   ttyLocker ttyl;  // keep the following output all in one block
   // print compiler name if requested
-  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler(comp_level())->name());
+  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
   print_compilation();
 }
 
@@ -508,7 +506,7 @@
   ResourceMark rm(thread);
 
   // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
-  if (_compile_id != 0)   log->print(" compile_id='%d'", _compile_id);
+  log->print(" compile_id='%d'", _compile_id);
   if (_osr_bci != CompileBroker::standard_entry_bci) {
     log->print(" compile_kind='osr'");  // same as nmethod::compile_kind
   } // else compile_kind='c2c'
@@ -1227,18 +1225,16 @@
   assert(method->method_holder()->oop_is_instance(), "not an instance method");
   assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
   assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
-  assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
-
-  if (!TieredCompilation) {
-    comp_level = CompLevel_highest_tier;
-  }
-
+  assert(!method->method_holder()->is_not_initialized() || method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "method holder must be initialized");
+  // allow any levels for WhiteBox
+  assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered");
   // return quickly if possible
 
   // lock, make sure that the compilation
   // isn't prohibited in a straightforward way.
-
-  if (compiler(comp_level) == NULL || !compiler(comp_level)->can_compile_method(method) || compilation_is_prohibited(method, osr_bci, comp_level)) {
+  AbstractCompiler *comp = CompileBroker::compiler(comp_level);
+  if (comp == NULL || !comp->can_compile_method(method) ||
+      compilation_is_prohibited(method, osr_bci, comp_level)) {
     return NULL;
   }
 
@@ -1275,7 +1271,7 @@
 
   assert(!HAS_PENDING_EXCEPTION, "No exception should be present");
   // some prerequisites that are compiler specific
-  if (compiler(comp_level)->is_c2() || compiler(comp_level)->is_shark()) {
+  if (comp->is_c2() || comp->is_shark()) {
     method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NULL);
     // Resolve all classes seen in the signature of the method
     // we are compiling.
@@ -1392,8 +1388,9 @@
 bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level) {
   bool is_native = method->is_native();
   // Some compilers may not support the compilation of natives.
+  AbstractCompiler *comp = compiler(comp_level);
   if (is_native &&
-      (!CICompileNatives || !compiler(comp_level)->supports_native())) {
+      (!CICompileNatives || comp == NULL || !comp->supports_native())) {
     method->set_not_compilable_quietly(comp_level);
     return true;
   }
@@ -1401,7 +1398,7 @@
   bool is_osr = (osr_bci != standard_entry_bci);
   // Some compilers may not support on stack replacement.
   if (is_osr &&
-      (!CICompileOSR || !compiler(comp_level)->supports_osr())) {
+      (!CICompileOSR || comp == NULL || !comp->supports_osr())) {
     method->set_not_osr_compilable(comp_level);
     return true;
   }
@@ -1773,6 +1770,7 @@
   bool is_osr = (osr_bci != standard_entry_bci);
   bool should_log = (thread->log() != NULL);
   bool should_break = false;
+  int task_level = task->comp_level();
   {
     // create the handle inside it's own block so it can't
     // accidentally be referenced once the thread transitions to
@@ -1786,9 +1784,10 @@
     assert(!method->is_native(), "no longer compile natives");
 
     // Save information about this method in case of failure.
-    set_last_compile(thread, method, is_osr, task->comp_level());
+    set_last_compile(thread, method, is_osr, task_level);
 
-    DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler(task->comp_level()), method);
+    DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler(task_level), method,
+                                      compiler_name(task_level));
   }
 
   // Allocate a new set of JNI handles.
@@ -1825,7 +1824,12 @@
 
     TraceTime t1("compilation", &time);
 
-    compiler(task->comp_level())->compile_method(&ci_env, target, osr_bci);
+    AbstractCompiler *comp = compiler(task_level);
+    if (comp == NULL) {
+      ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
+    } else {
+      comp->compile_method(&ci_env, target, osr_bci);
+    }
 
     if (!ci_env.failing() && task->code() == NULL) {
       //assert(false, "compiler should always document failure");
@@ -1863,7 +1867,8 @@
 
   methodHandle method(thread, task->method());
 
-  DTRACE_METHOD_COMPILE_END_PROBE(compiler(task->comp_level()), method, task->is_success());
+  DTRACE_METHOD_COMPILE_END_PROBE(compiler(task_level), method,
+                                  compiler_name(task_level), task->is_success());
 
   collect_statistics(thread, time, task);
 
@@ -1888,9 +1893,9 @@
     break;
   case ciEnv::MethodCompilable_not_at_tier:
     if (is_osr)
-      method->set_not_osr_compilable_quietly(task->comp_level());
+      method->set_not_osr_compilable_quietly(task_level);
     else
-      method->set_not_compilable_quietly(task->comp_level());
+      method->set_not_compilable_quietly(task_level);
     break;
   }
 
@@ -2156,7 +2161,14 @@
   if (UsePerfData) counters->set_current_method("");
 }
 
-
+const char* CompileBroker::compiler_name(int comp_level) {
+  AbstractCompiler *comp = CompileBroker::compiler(comp_level);
+  if (comp == NULL) {
+    return "no compiler";
+  } else {
+    return (comp->name());
+  }
+}
 
 void CompileBroker::print_times() {
   tty->cr();
@@ -2170,13 +2182,18 @@
                 CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
   tty->print_cr("    On stack replacement   : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
 
-  if (compiler(CompLevel_simple) != NULL) {
-    compiler(CompLevel_simple)->print_timers();
+  AbstractCompiler *comp = compiler(CompLevel_simple);
+  if (comp != NULL) {
+    comp->print_timers();
   }
-  if (compiler(CompLevel_full_optimization) != NULL) {
-    compiler(CompLevel_full_optimization)->print_timers();
+  comp = compiler(CompLevel_full_optimization);
+  if (comp != NULL) {
+    comp->print_timers();
   }
   tty->cr();
+  tty->print_cr("  Total compiled methods   : %6d methods", CompileBroker::_total_compile_count);
+  tty->print_cr("    Standard compilation   : %6d methods", CompileBroker::_total_standard_compile_count);
+  tty->print_cr("    On stack replacement   : %6d methods", CompileBroker::_total_osr_compile_count);
   int tcb = CompileBroker::_sum_osr_bytes_compiled + CompileBroker::_sum_standard_bytes_compiled;
   tty->print_cr("  Total compiled bytecodes : %6d bytes", tcb);
   tty->print_cr("    Standard compilation   : %6d bytes", CompileBroker::_sum_standard_bytes_compiled);
--- a/src/share/vm/compiler/compileBroker.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/compileBroker.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -418,6 +418,9 @@
   static void print_last_compile();
 
   static void print_compiler_threads_on(outputStream* st);
+
+  // compiler name for debugging
+  static const char* compiler_name(int comp_level);
 };
 
 #endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP
--- a/src/share/vm/compiler/compileLog.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/compileLog.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -60,28 +60,6 @@
 }
 
 
-// Advance kind up to a null or space, return this tail.
-// Make sure kind is null-terminated, not space-terminated.
-// Use the buffer if necessary.
-static const char* split_attrs(const char* &kind, char* buffer) {
-  const char* attrs = strchr(kind, ' ');
-  // Tease apart the first word from the rest:
-  if (attrs == NULL) {
-    return "";  // no attrs, no split
-  } else if (kind == buffer) {
-    ((char*) attrs)[-1] = 0;
-    return attrs;
-  } else {
-    // park it in the buffer, so we can put a null on the end
-    assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer");
-    int klen = attrs - kind;
-    strncpy(buffer, kind, klen);
-    buffer[klen] = 0;
-    kind = buffer;  // return by reference
-    return attrs;
-  }
-}
-
 // see_tag, pop_tag:  Override the default do-nothing methods on xmlStream.
 // These methods provide a hook for managing the the extra context markup.
 void CompileLog::see_tag(const char* tag, bool push) {
--- a/src/share/vm/compiler/compilerOracle.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/compilerOracle.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -237,13 +237,6 @@
   "help"
 };
 
-static const char * command_name(OracleCommand command) {
-  if (command < OracleFirstCommand || command >= OracleCommandCount) {
-    return "unknown command";
-  }
-  return command_names[command];
-}
-
 class MethodMatcher;
 static MethodMatcher* lists[OracleCommandCount] = { 0, };
 
--- a/src/share/vm/compiler/disassembler.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/disassembler.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -158,7 +158,7 @@
  private:
   nmethod*      _nm;
   CodeBlob*     _code;
-  CodeComments  _comments;
+  CodeStrings   _strings;
   outputStream* _output;
   address       _start, _end;
 
@@ -198,7 +198,7 @@
   void print_address(address value);
 
  public:
-  decode_env(CodeBlob* code, outputStream* output, CodeComments c = CodeComments());
+  decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings());
 
   address decode_instructions(address start, address end);
 
@@ -242,13 +242,13 @@
   const char* options() { return _option_buf; }
 };
 
-decode_env::decode_env(CodeBlob* code, outputStream* output, CodeComments c) {
+decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) {
   memset(this, 0, sizeof(*this));
   _output = output ? output : tty;
   _code = code;
   if (code != NULL && code->is_nmethod())
     _nm = (nmethod*) code;
-  _comments.assign(c);
+  _strings.assign(c);
 
   // by default, output pc but not bytes:
   _print_pc       = true;
@@ -370,7 +370,7 @@
   if (cb != NULL) {
     cb->print_block_comment(st, p);
   }
-  _comments.print_block_comment(st, (intptr_t)(p - _start));
+  _strings.print_block_comment(st, (intptr_t)(p - _start));
   if (_print_pc) {
     st->print("  " PTR_FORMAT ": ", p);
   }
@@ -499,7 +499,7 @@
   env.decode_instructions(cb->code_begin(), cb->code_end());
 }
 
-void Disassembler::decode(address start, address end, outputStream* st, CodeComments c) {
+void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c) {
   if (!load_library())  return;
   decode_env env(CodeCache::find_blob_unsafe(start), st, c);
   env.decode_instructions(start, end);
--- a/src/share/vm/compiler/disassembler.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/compiler/disassembler.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -100,7 +100,7 @@
   }
   static void decode(CodeBlob *cb,               outputStream* st = NULL);
   static void decode(nmethod* nm,                outputStream* st = NULL);
-  static void decode(address begin, address end, outputStream* st = NULL, CodeComments c = CodeComments());
+  static void decode(address begin, address end, outputStream* st = NULL, CodeStrings c = CodeStrings());
 };
 
 #endif // SHARE_VM_COMPILER_DISASSEMBLER_HPP
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -48,6 +48,7 @@
 #include "memory/iterator.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/resourceArea.hpp"
+#include "memory/tenuredGeneration.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/globals_extension.hpp"
@@ -916,7 +917,31 @@
     return;
   }
 
-  size_t expand_bytes = 0;
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  CardGeneration::compute_new_size();
+
+  // Reset again after a possible resizing
+  cmsSpace()->reset_after_compaction();
+
+  assert(used() == used_after_gc && used_after_gc <= capacity(),
+         err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
+         " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()));
+}
+
+void ConcurrentMarkSweepGeneration::compute_new_size_free_list() {
+  assert_locked_or_safepoint(Heap_lock);
+
+  // If incremental collection failed, we just want to expand
+  // to the limit.
+  if (incremental_collection_failed()) {
+    clear_incremental_collection_failed();
+    grow_to_reserved();
+    return;
+  }
+
   double free_percentage = ((double) free()) / capacity();
   double desired_free_percentage = (double) MinHeapFreeRatio / 100;
   double maximum_free_percentage = (double) MaxHeapFreeRatio / 100;
@@ -925,9 +950,7 @@
   if (free_percentage < desired_free_percentage) {
     size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
     assert(desired_capacity >= capacity(), "invalid expansion size");
-    expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
-  }
-  if (expand_bytes > 0) {
+    size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
     if (PrintGCDetails && Verbose) {
       size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
       gclog_or_tty->print_cr("\nFrom compute_new_size: ");
@@ -961,6 +984,14 @@
       gclog_or_tty->print_cr("  Expanded free fraction %f",
         ((double) free()) / capacity());
     }
+  } else {
+    size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
+    assert(desired_capacity <= capacity(), "invalid expansion size");
+    size_t shrink_bytes = capacity() - desired_capacity;
+    // Don't shrink unless the delta is greater than the minimum shrink we want
+    if (shrink_bytes >= MinHeapDeltaBytes) {
+      shrink_free_list_by(shrink_bytes);
+    }
   }
 }
 
@@ -1872,7 +1903,7 @@
   assert_locked_or_safepoint(Heap_lock);
   FreelistLocker z(this);
   MetaspaceGC::compute_new_size();
-  _cmsGen->compute_new_size();
+  _cmsGen->compute_new_size_free_list();
 }
 
 // A work method used by foreground collection to determine
@@ -2063,11 +2094,6 @@
       // required.
       _collectorState = FinalMarking;
   }
-  if (PrintGCDetails &&
-      (_collectorState > Idling ||
-       !GCCause::is_user_requested_gc(GenCollectedHeap::heap()->gc_cause()))) {
-    gclog_or_tty->print(" (concurrent mode failure)");
-  }
   collect_in_foreground(clear_all_soft_refs);
 
   // For a mark-sweep, compute_new_size() will be called
@@ -2606,6 +2632,10 @@
 }
 
 void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
+
+  _capacity_at_prologue = capacity();
+  _used_at_prologue = used();
+
   // Delegate to CMScollector which knows how to coordinate between
   // this and any other CMS generations that it is responsible for
   // collecting.
@@ -2779,6 +2809,23 @@
   }
 }
 
+
+void
+CMSCollector::print_on_error(outputStream* st) {
+  CMSCollector* collector = ConcurrentMarkSweepGeneration::_collector;
+  if (collector != NULL) {
+    CMSBitMap* bitmap = &collector->_markBitMap;
+    st->print_cr("Marking Bits: (CMSBitMap*) " PTR_FORMAT, bitmap);
+    bitmap->print_on_error(st, " Bits: ");
+
+    st->cr();
+
+    CMSBitMap* mut_bitmap = &collector->_modUnionTable;
+    st->print_cr("Mod Union Table: (CMSBitMap*) " PTR_FORMAT, mut_bitmap);
+    mut_bitmap->print_on_error(st, " Bits: ");
+  }
+}
+
 ////////////////////////////////////////////////////////
 // CMS Verification Support
 ////////////////////////////////////////////////////////
@@ -3305,6 +3352,26 @@
 }
 
 
+void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
+  assert_locked_or_safepoint(ExpandHeap_lock);
+  // Shrink committed space
+  _virtual_space.shrink_by(bytes);
+  // Shrink space; this also shrinks the space's BOT
+  _cmsSpace->set_end((HeapWord*) _virtual_space.high());
+  size_t new_word_size = heap_word_size(_cmsSpace->capacity());
+  // Shrink the shared block offset array
+  _bts->resize(new_word_size);
+  MemRegion mr(_cmsSpace->bottom(), new_word_size);
+  // Shrink the card table
+  Universe::heap()->barrier_set()->resize_covered_region(mr);
+
+  if (Verbose && PrintGC) {
+    size_t new_mem_size = _virtual_space.committed_size();
+    size_t old_mem_size = new_mem_size + bytes;
+    gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
+                  name(), old_mem_size/K, new_mem_size/K);
+  }
+}
 
 void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
   assert_locked_or_safepoint(Heap_lock);
@@ -3356,7 +3423,7 @@
   return success;
 }
 
-void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
+void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) {
   assert_locked_or_safepoint(Heap_lock);
   assert_lock_strong(freelistLock());
   // XXX Fix when compaction is implemented.
@@ -3400,10 +3467,10 @@
   if (PrintCMSStatistics != 0) {
     _collector->resetYields();
   }
-  if (PrintGCDetails && PrintGCTimeStamps) {
+  if (PrintGCDetails) {
     gclog_or_tty->date_stamp(PrintGCDateStamps);
-    gclog_or_tty->stamp();
-    gclog_or_tty->print_cr(": [%s-concurrent-%s-start]",
+    gclog_or_tty->stamp(PrintGCTimeStamps);
+    gclog_or_tty->print_cr("[%s-concurrent-%s-start]",
       _collector->cmsGen()->short_name(), _phase);
   }
   _collector->resetTimer();
@@ -6073,6 +6140,10 @@
   verify_work_stacks_empty();
   verify_overflow_empty();
 
+  if (should_unload_classes()) {
+    ClassLoaderDataGraph::purge();
+  }
+
   _intra_sweep_timer.stop();
   _intra_sweep_estimate.sample(_intra_sweep_timer.seconds());
 
@@ -6477,6 +6548,10 @@
   }
 }
 
+void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const {
+  _bm.print_on_error(st, prefix);
+}
+
 #ifndef PRODUCT
 void CMSBitMap::assert_locked() const {
   CMSLockVerifier::assert_locked(lock());
@@ -9075,51 +9150,6 @@
   }
 }
 
-// The desired expansion delta is computed so that:
-// . desired free percentage or greater is used
-void ASConcurrentMarkSweepGeneration::compute_new_size() {
-  assert_locked_or_safepoint(Heap_lock);
-
-  GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap();
-
-  // If incremental collection failed, we just want to expand
-  // to the limit.
-  if (incremental_collection_failed()) {
-    clear_incremental_collection_failed();
-    grow_to_reserved();
-    return;
-  }
-
-  assert(UseAdaptiveSizePolicy, "Should be using adaptive sizing");
-
-  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
-    "Wrong type of heap");
-  int prev_level = level() - 1;
-  assert(prev_level >= 0, "The cms generation is the lowest generation");
-  Generation* prev_gen = gch->get_gen(prev_level);
-  assert(prev_gen->kind() == Generation::ASParNew,
-    "Wrong type of young generation");
-  ParNewGeneration* younger_gen = (ParNewGeneration*) prev_gen;
-  size_t cur_eden = younger_gen->eden()->capacity();
-  CMSAdaptiveSizePolicy* size_policy = cms_size_policy();
-  size_t cur_promo = free();
-  size_policy->compute_tenured_generation_free_space(cur_promo,
-                                                       max_available(),
-                                                       cur_eden);
-  resize(cur_promo, size_policy->promo_size());
-
-  // Record the new size of the space in the cms generation
-  // that is available for promotions.  This is temporary.
-  // It should be the desired promo size.
-  size_policy->avg_cms_promo()->sample(free());
-  size_policy->avg_old_live()->sample(used());
-
-  if (UsePerfData) {
-    CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters();
-    counters->update_cms_capacity_counter(capacity());
-  }
-}
-
 void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) {
   assert_locked_or_safepoint(Heap_lock);
   assert_lock_strong(freelistLock());
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -60,6 +60,7 @@
 class FreeChunk;
 class PromotionInfo;
 class ScanMarkedObjectsAgainCarefullyClosure;
+class TenuredGeneration;
 
 // A generic CMS bit map. It's the basis for both the CMS marking bit map
 // as well as for the mod union table (in each case only a subset of the
@@ -150,6 +151,8 @@
   size_t    heapWordToOffset(HeapWord* addr) const;
   size_t    heapWordDiffToOffsetDiff(size_t diff) const;
 
+  void print_on_error(outputStream* st, const char* prefix) const;
+
   // debugging
   // is this address range covered by the bit-map?
   NOT_PRODUCT(
@@ -810,9 +813,6 @@
   // used regions of each generation to limit the extent of sweep
   void save_sweep_limits();
 
-  // Resize the generations included in the collector.
-  void compute_new_size();
-
   // A work method used by foreground collection to determine
   // what type of collection (compacting or not, continuing or fresh)
   // it should do.
@@ -909,6 +909,9 @@
   void releaseFreelistLocks() const;
   bool haveFreelistLocks() const;
 
+  // Adjust size of underlying generation
+  void compute_new_size();
+
   // GC prologue and epilogue
   void gc_prologue(bool full);
   void gc_epilogue(bool full);
@@ -983,6 +986,8 @@
   CMSAdaptiveSizePolicy* size_policy();
   CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters();
 
+  static void print_on_error(outputStream* st);
+
   // debugging
   void verify();
   bool verify_after_remark();
@@ -1082,7 +1087,7 @@
 
  protected:
   // Shrink generation by specified size (returns false if unable to shrink)
-  virtual void shrink_by(size_t bytes);
+  void shrink_free_list_by(size_t bytes);
 
   // Update statistics for GC
   virtual void update_gc_stats(int level, bool full);
@@ -1233,6 +1238,7 @@
     CMSExpansionCause::Cause cause);
   virtual bool expand(size_t bytes, size_t expand_bytes);
   void shrink(size_t bytes);
+  void shrink_by(size_t bytes);
   HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
   bool expand_and_ensure_spooling_space(PromotionInfo* promo);
 
@@ -1293,7 +1299,13 @@
   bool must_be_youngest() const { return false; }
   bool must_be_oldest()   const { return true; }
 
-  void compute_new_size();
+  // Resize the generation after a compacting GC.  The
+  // generation can be treated as a contiguous space
+  // after the compaction.
+  virtual void compute_new_size();
+  // Resize the generation after a non-compacting
+  // collection.
+  void compute_new_size_free_list();
 
   CollectionTypes debug_collection_type() { return _debug_collection_type; }
   void rotate_debug_collection_type();
@@ -1315,7 +1327,6 @@
   virtual void shrink_by(size_t bytes);
 
  public:
-  virtual void compute_new_size();
   ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                   int level, CardTableRS* ct,
                                   bool use_adaptive_freelists,
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -300,8 +300,7 @@
   }
 }
 
-// Wait until the next synchronous GC, a concurrent full gc request,
-// or a timeout, whichever is earlier.
+// Wait until any cms_lock event
 void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
   MutexLockerEx x(CGC_lock,
                   Mutex::_no_safepoint_check_flag);
@@ -315,15 +314,100 @@
          "Should not be set");
 }
 
+// Wait until the next synchronous GC, a concurrent full gc request,
+// or a timeout, whichever is earlier.
+void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {
+  // Wait time in millis or 0 value representing infinite wait for a scavenge
+  assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive");
+
+  GenCollectedHeap* gch = GenCollectedHeap::heap();
+  double start_time_secs = os::elapsedTime();
+  double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS));
+
+  // Total collections count before waiting loop
+  unsigned int before_count;
+  {
+    MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+    before_count = gch->total_collections();
+  }
+
+  unsigned int loop_count = 0;
+
+  while(!_should_terminate) {
+    double now_time = os::elapsedTime();
+    long wait_time_millis;
+
+    if(t_millis != 0) {
+      // New wait limit
+      wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS);
+      if(wait_time_millis <= 0) {
+        // Wait time is over
+        break;
+      }
+    } else {
+      // No wait limit, wait if necessary forever
+      wait_time_millis = 0;
+    }
+
+    // Wait until the next event or the remaining timeout
+    {
+      MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+
+      if (_should_terminate || _collector->_full_gc_requested) {
+        return;
+      }
+      set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
+      assert(t_millis == 0 || wait_time_millis > 0, "Sanity");
+      CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis);
+      clear_CMS_flag(CMS_cms_wants_token);
+      assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
+             "Should not be set");
+    }
+
+    // Extra wait time check before entering the heap lock to get the collection count
+    if(t_millis != 0 && os::elapsedTime() >= end_time_secs) {
+      // Wait time is over
+      break;
+    }
+
+    // Total collections count after the event
+    unsigned int after_count;
+    {
+      MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+      after_count = gch->total_collections();
+    }
+
+    if(before_count != after_count) {
+      // There was a collection - success
+      break;
+    }
+
+    // Too many loops warning
+    if(++loop_count == 0) {
+      warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1);
+    }
+  }
+}
+
 void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
   while (!_should_terminate) {
     if (CMSIncrementalMode) {
       icms_wait();
+      if(CMSWaitDuration >= 0) {
+        // Wait until the next synchronous GC, a concurrent full gc
+        // request or a timeout, whichever is earlier.
+        wait_on_cms_lock_for_scavenge(CMSWaitDuration);
+      }
       return;
     } else {
-      // Wait until the next synchronous GC, a concurrent full gc
-      // request or a timeout, whichever is earlier.
-      wait_on_cms_lock(CMSWaitDuration);
+      if(CMSWaitDuration >= 0) {
+        // Wait until the next synchronous GC, a concurrent full gc
+        // request or a timeout, whichever is earlier.
+        wait_on_cms_lock_for_scavenge(CMSWaitDuration);
+      } else {
+        // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently
+        wait_on_cms_lock(CMSCheckInterval);
+      }
     }
     // Check if we should start a CMS collection cycle
     if (_collector->shouldConcurrentCollect()) {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -130,6 +130,12 @@
   // A concurrent full gc request terminates the wait.
   void wait_on_cms_lock(long t_millis);
 
+  // Wait on CMS lock until the next synchronous GC
+  // or given timeout, whichever is earlier. A timeout value
+  // of 0 indicates that there is no upper bound on the wait time.
+  // A concurrent full gc request terminates the wait.
+  void wait_on_cms_lock_for_scavenge(long t_millis);
+
   // The CMS thread will yield during the work portion of its cycle
   // only when requested to.  Both synchronous and asychronous requests
   // are provided:
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -146,43 +146,6 @@
   verify();
 }
 
-uint CollectionSetChooser::calc_min_old_cset_length() {
-  // The min old CSet region bound is based on the maximum desired
-  // number of mixed GCs after a cycle. I.e., even if some old regions
-  // look expensive, we should add them to the CSet anyway to make
-  // sure we go through the available old regions in no more than the
-  // maximum desired number of mixed GCs.
-  //
-  // The calculation is based on the number of marked regions we added
-  // to the CSet chooser in the first place, not how many remain, so
-  // that the result is the same during all mixed GCs that follow a cycle.
-
-  const size_t region_num = (size_t) _length;
-  const size_t gc_num = (size_t) G1MixedGCCountTarget;
-  size_t result = region_num / gc_num;
-  // emulate ceiling
-  if (result * gc_num < region_num) {
-    result += 1;
-  }
-  return (uint) result;
-}
-
-uint CollectionSetChooser::calc_max_old_cset_length() {
-  // The max old CSet region bound is based on the threshold expressed
-  // as a percentage of the heap size. I.e., it should bound the
-  // number of old regions added to the CSet irrespective of how many
-  // of them are available.
-
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  const size_t region_num = g1h->n_regions();
-  const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
-  size_t result = region_num * perc / 100;
-  // emulate ceiling
-  if (100 * result < region_num * perc) {
-    result += 1;
-  }
-  return (uint) result;
-}
 
 void CollectionSetChooser::add_region(HeapRegion* hr) {
   assert(!hr->isHumongous(),
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -51,6 +51,8 @@
   uint _curr_index;
 
   // The number of candidate old regions added to the CSet chooser.
+  // Note: this is not updated when removing a region using
+  // remove_and_move_to_next() below.
   uint _length;
 
   // Keeps track of the start of the next array chunk to be claimed by
@@ -111,13 +113,8 @@
             hr->live_bytes() < _region_live_threshold_bytes;
   }
 
-  // Calculate the minimum number of old regions we'll add to the CSet
-  // during a mixed GC.
-  uint calc_min_old_cset_length();
-
-  // Calculate the maximum number of old regions we'll add to the CSet
-  // during a mixed GC.
-  uint calc_max_old_cset_length();
+  // Returns the number candidate old regions added
+  uint length() { return _length; }
 
   // Serial version.
   void add_region(HeapRegion *hr);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -101,6 +101,10 @@
 }
 #endif
 
+void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const {
+  _bm.print_on_error(st, prefix);
+}
+
 bool CMBitMap::allocate(ReservedSpace heap_rs) {
   _bmStartWord = (HeapWord*)(heap_rs.base());
   _bmWordSize  = heap_rs.size()/HeapWordSize;    // heap_rs.size() is in bytes
@@ -784,7 +788,7 @@
   }
 }
 
-void ConcurrentMark::set_phase(uint active_tasks, bool concurrent) {
+void ConcurrentMark::set_concurrency(uint active_tasks) {
   assert(active_tasks <= _max_worker_id, "we should not have more");
 
   _active_tasks = active_tasks;
@@ -793,6 +797,10 @@
   _terminator   = ParallelTaskTerminator((int) active_tasks, _task_queues);
   _first_overflow_barrier_sync.set_n_workers((int) active_tasks);
   _second_overflow_barrier_sync.set_n_workers((int) active_tasks);
+}
+
+void ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurrent) {
+  set_concurrency(active_tasks);
 
   _concurrent = concurrent;
   // We propagate this to all tasks, not just the active ones.
@@ -806,7 +814,9 @@
     // false before we start remark. At this point we should also be
     // in a STW phase.
     assert(!concurrent_marking_in_progress(), "invariant");
-    assert(_finger == _heap_end, "only way to get here");
+    assert(_finger == _heap_end,
+           err_msg("only way to get here: _finger: "PTR_FORMAT", _heap_end: "PTR_FORMAT,
+                   _finger, _heap_end));
     update_g1_committed(true);
   }
 }
@@ -974,20 +984,28 @@
     gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id);
   }
 
-  // let the task associated with with worker 0 do this
-  if (worker_id == 0) {
-    // task 0 is responsible for clearing the global data structures
-    // We should be here because of an overflow. During STW we should
-    // not clear the overflow flag since we rely on it being true when
-    // we exit this method to abort the pause and restart concurent
-    // marking.
-    reset_marking_state(concurrent() /* clear_overflow */);
-    force_overflow()->update();
-
-    if (G1Log::fine()) {
-      gclog_or_tty->date_stamp(PrintGCDateStamps);
-      gclog_or_tty->stamp(PrintGCTimeStamps);
-      gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]");
+  // If we're executing the concurrent phase of marking, reset the marking
+  // state; otherwise the marking state is reset after reference processing,
+  // during the remark pause.
+  // If we reset here as a result of an overflow during the remark we will
+  // see assertion failures from any subsequent set_concurrency_and_phase()
+  // calls.
+  if (concurrent()) {
+    // let the task associated with with worker 0 do this
+    if (worker_id == 0) {
+      // task 0 is responsible for clearing the global data structures
+      // We should be here because of an overflow. During STW we should
+      // not clear the overflow flag since we rely on it being true when
+      // we exit this method to abort the pause and restart concurent
+      // marking.
+      reset_marking_state(true /* clear_overflow */);
+      force_overflow()->update();
+
+      if (G1Log::fine()) {
+        gclog_or_tty->date_stamp(PrintGCDateStamps);
+        gclog_or_tty->stamp(PrintGCTimeStamps);
+        gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]");
+      }
     }
   }
 
@@ -1007,7 +1025,7 @@
   if (concurrent()) {
     ConcurrentGCThread::stsJoin();
   }
-  // at this point everything should be re-initialised and ready to go
+  // at this point everything should be re-initialized and ready to go
 
   if (verbose_low()) {
     gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id);
@@ -1065,8 +1083,8 @@
         double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
 
         the_task->do_marking_step(mark_step_duration_ms,
-                                  true /* do_stealing    */,
-                                  true /* do_termination */);
+                                  true  /* do_termination */,
+                                  false /* is_serial*/);
 
         double end_time_sec = os::elapsedTime();
         double end_vtime_sec = os::elapsedVTime();
@@ -1222,8 +1240,8 @@
 
   uint active_workers = MAX2(1U, parallel_marking_threads());
 
-  // Parallel task terminator is set in "set_phase()"
-  set_phase(active_workers, true /* concurrent */);
+  // Parallel task terminator is set in "set_concurrency_and_phase()"
+  set_concurrency_and_phase(active_workers, true /* concurrent */);
 
   CMConcurrentMarkingTask markingTask(this, cmThread());
   if (use_parallel_marking_threads()) {
@@ -1275,12 +1293,22 @@
   if (has_overflown()) {
     // Oops.  We overflowed.  Restart concurrent marking.
     _restart_for_overflow = true;
+    if (G1TraceMarkStackOverflow) {
+      gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
+    }
+
+    // Verify the heap w.r.t. the previous marking bitmap.
+    if (VerifyDuringGC) {
+      HandleMark hm;  // handle scope
+      gclog_or_tty->print(" VerifyDuringGC:(overflow)");
+      Universe::heap()->prepare_for_verify();
+      Universe::verify(/* silent */ false,
+                       /* option */ VerifyOption_G1UsePrevMarking);
+    }
+
     // Clear the marking state because we will be restarting
     // marking due to overflowing the global mark stack.
     reset_marking_state();
-    if (G1TraceMarkStackOverflow) {
-      gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
-    }
   } else {
     // Aggregate the per-task counting data that we have accumulated
     // while marking.
@@ -1310,11 +1338,6 @@
     _markStack.expand();
   }
 
-#if VERIFY_OBJS_PROCESSED
-  _scan_obj_cl.objs_processed = 0;
-  ThreadLocalObjQueue::objs_enqueued = 0;
-#endif
-
   // Statistics
   double now = os::elapsedTime();
   _remark_mark_times.add((mark_work_end - start) * 1000.0);
@@ -2189,14 +2212,17 @@
 // operating on the global stack.
 
 class G1CMKeepAliveAndDrainClosure: public OopClosure {
-  ConcurrentMark*  _cm;
-  CMTask*          _task;
-  int              _ref_counter_limit;
-  int              _ref_counter;
+  ConcurrentMark* _cm;
+  CMTask*         _task;
+  int             _ref_counter_limit;
+  int             _ref_counter;
+  bool            _is_serial;
  public:
-  G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) :
-    _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) {
+  G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task, bool is_serial) :
+    _cm(cm), _task(task), _is_serial(is_serial),
+    _ref_counter_limit(G1RefProcDrainInterval) {
     assert(_ref_counter_limit > 0, "sanity");
+    assert(!_is_serial || _task->worker_id() == 0, "only task 0 for serial code");
     _ref_counter = _ref_counter_limit;
   }
 
@@ -2235,8 +2261,8 @@
         do {
           double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
           _task->do_marking_step(mark_step_duration_ms,
-                                 false /* do_stealing    */,
-                                 false /* do_termination */);
+                                 false      /* do_termination */,
+                                 _is_serial);
         } while (_task->has_aborted() && !_cm->has_overflown());
         _ref_counter = _ref_counter_limit;
       }
@@ -2258,27 +2284,18 @@
 class G1CMDrainMarkingStackClosure: public VoidClosure {
   ConcurrentMark* _cm;
   CMTask*         _task;
-  bool            _do_stealing;
-  bool            _do_termination;
+  bool            _is_serial;
  public:
-  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;
+  G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_serial) :
+    _cm(cm), _task(task), _is_serial(is_serial) {
+    assert(!_is_serial || _task->worker_id() == 0, "only task 0 for serial code");
   }
 
   void do_void() {
     do {
       if (_cm->verbose_high()) {
-        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));
+        gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - serial: %s",
+                               _task->worker_id(), BOOL_TO_STR(_is_serial));
       }
 
       // We call CMTask::do_marking_step() to completely drain the local
@@ -2299,8 +2316,8 @@
       // has_aborted() flag that the marking step has completed.
 
       _task->do_marking_step(1000000000.0 /* something very large */,
-                             _do_stealing,
-                             _do_termination);
+                             true         /* do_termination */,
+                             _is_serial);
     } while (_task->has_aborted() && !_cm->has_overflown());
   }
 };
@@ -2333,7 +2350,6 @@
   ProcessTask&     _proc_task;
   G1CollectedHeap* _g1h;
   ConcurrentMark*  _cm;
-  bool             _processing_is_mt;
 
 public:
   G1CMRefProcTaskProxy(ProcessTask& proc_task,
@@ -2341,15 +2357,15 @@
                      ConcurrentMark* cm) :
     AbstractGangTask("Process reference objects in parallel"),
     _proc_task(proc_task), _g1h(g1h), _cm(cm) {
-      ReferenceProcessor* rp = _g1h->ref_processor_cm();
-      _processing_is_mt = rp->processing_is_mt();
-    }
+    ReferenceProcessor* rp = _g1h->ref_processor_cm();
+    assert(rp->processing_is_mt(), "shouldn't be here otherwise");
+  }
 
   virtual void work(uint worker_id) {
-    CMTask* marking_task = _cm->task(worker_id);
+    CMTask* task = _cm->task(worker_id);
     G1CMIsAliveClosure g1_is_alive(_g1h);
-    G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task);
-    G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt);
+    G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */);
+    G1CMDrainMarkingStackClosure g1_par_drain(_cm, task, false /* is_serial */);
 
     _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain);
   }
@@ -2361,9 +2377,11 @@
 
   G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm);
 
-  // We need to reset the phase for each task execution so that
-  // the termination protocol of CMTask::do_marking_step works.
-  _cm->set_phase(_active_workers, false /* concurrent */);
+  // We need to reset the concurrency level before each
+  // proxy task execution, so that the termination protocol
+  // and overflow handling in CMTask::do_marking_step() knows
+  // how many workers to wait for.
+  _cm->set_concurrency(_active_workers);
   _g1h->set_par_threads(_active_workers);
   _workers->run_task(&proc_task_proxy);
   _g1h->set_par_threads(0);
@@ -2389,12 +2407,29 @@
 
   G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task);
 
+  // Not strictly necessary but...
+  //
+  // We need to reset the concurrency level before each
+  // proxy task execution, so that the termination protocol
+  // and overflow handling in CMTask::do_marking_step() knows
+  // how many workers to wait for.
+  _cm->set_concurrency(_active_workers);
   _g1h->set_par_threads(_active_workers);
   _workers->run_task(&enq_task_proxy);
   _g1h->set_par_threads(0);
 }
 
 void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
+  if (has_overflown()) {
+    // Skip processing the discovered references if we have
+    // overflown the global marking stack. Reference objects
+    // only get discovered once so it is OK to not
+    // de-populate the discovered reference lists. We could have,
+    // but the only benefit would be that, when marking restarts,
+    // less reference objects are discovered.
+    return;
+  }
+
   ResourceMark rm;
   HandleMark   hm;
 
@@ -2420,26 +2455,39 @@
     rp->setup_policy(clear_all_soft_refs);
     assert(_markStack.isEmpty(), "mark stack should be empty");
 
-    // 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);
-
+    // Instances of the 'Keep Alive' and 'Complete GC' closures used
+    // in serial reference processing. Note these closures are also
+    // used for serially processing (by the the current thread) the
+    // JNI references during parallel reference processing.
+    //
+    // These closures do not need to synchronize with the worker
+    // threads involved in parallel reference processing as these
+    // instances are executed serially by the current thread (e.g.
+    // reference processing is not multi-threaded and is thus
+    // performed by the current thread instead of a gang worker).
+    //
+    // The gang tasks involved in parallel reference procssing create
+    // their own instances of these closures, which do their own
+    // synchronization among themselves.
+    G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0), true /* is_serial */);
+    G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), true /* is_serial */);
+
+    // We need at least one active thread. If reference processing
+    // is not multi-threaded we use the current (VMThread) thread,
+    // otherwise we use the work gang from the G1CollectedHeap and
+    // we utilize all the worker threads we can.
+    bool processing_is_mt = rp->processing_is_mt() && g1h->workers() != NULL;
+    uint active_workers = (processing_is_mt ? g1h->workers()->active_workers() : 1U);
     active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U);
 
+    // Parallel processing task executor.
     G1CMRefProcTaskExecutor par_task_executor(g1h, this,
                                               g1h->workers(), active_workers);
-
-    AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt()
-                                                ? &par_task_executor
-                                                : NULL);
+    AbstractRefProcTaskExecutor* executor = (processing_is_mt ? &par_task_executor : NULL);
+
+    // Set the concurrency level. The phase was already set prior to
+    // executing the remark task.
+    set_concurrency(active_workers);
 
     // Set the degree of MT processing here.  If the discovery was done MT,
     // the number of threads involved during discovery could differ from
@@ -2459,6 +2507,7 @@
 
     assert(_markStack.overflow() || _markStack.isEmpty(),
             "mark stack should be empty (unless it overflowed)");
+
     if (_markStack.overflow()) {
       // 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.
@@ -2487,8 +2536,8 @@
 
 class CMRemarkTask: public AbstractGangTask {
 private:
-  ConcurrentMark *_cm;
-
+  ConcurrentMark* _cm;
+  bool            _is_serial;
 public:
   void work(uint worker_id) {
     // Since all available tasks are actually started, we should
@@ -2498,8 +2547,8 @@
       task->record_start_time();
       do {
         task->do_marking_step(1000000000.0 /* something very large */,
-                              true /* do_stealing    */,
-                              true /* do_termination */);
+                              true         /* do_termination       */,
+                              _is_serial);
       } while (task->has_aborted() && !_cm->has_overflown());
       // If we overflow, then we do not want to restart. We instead
       // want to abort remark and do concurrent marking again.
@@ -2507,8 +2556,8 @@
     }
   }
 
-  CMRemarkTask(ConcurrentMark* cm, int active_workers) :
-    AbstractGangTask("Par Remark"), _cm(cm) {
+  CMRemarkTask(ConcurrentMark* cm, int active_workers, bool is_serial) :
+    AbstractGangTask("Par Remark"), _cm(cm), _is_serial(is_serial) {
     _cm->terminator()->reset_for_reuse(active_workers);
   }
 };
@@ -2529,43 +2578,42 @@
       active_workers = (uint) ParallelGCThreads;
       g1h->workers()->set_active_workers(active_workers);
     }
-    set_phase(active_workers, false /* concurrent */);
+    set_concurrency_and_phase(active_workers, false /* concurrent */);
     // Leave _parallel_marking_threads at it's
     // value originally calculated in the ConcurrentMark
     // constructor and pass values of the active workers
     // through the gang in the task.
 
-    CMRemarkTask remarkTask(this, active_workers);
+    CMRemarkTask remarkTask(this, active_workers, false /* is_serial */);
+    // We will start all available threads, even if we decide that the
+    // active_workers will be fewer. The extra ones will just bail out
+    // immediately.
     g1h->set_par_threads(active_workers);
     g1h->workers()->run_task(&remarkTask);
     g1h->set_par_threads(0);
   } else {
     G1CollectedHeap::StrongRootsScope srs(g1h);
-    // this is remark, so we'll use up all available threads
     uint active_workers = 1;
-    set_phase(active_workers, false /* concurrent */);
-
-    CMRemarkTask remarkTask(this, active_workers);
-    // We will start all available threads, even if we decide that the
-    // active_workers will be fewer. The extra ones will just bail out
-    // immediately.
+    set_concurrency_and_phase(active_workers, false /* concurrent */);
+
+    // Note - if there's no work gang then the VMThread will be
+    // the thread to execute the remark - serially. We have
+    // to pass true for the is_serial parameter so that
+    // CMTask::do_marking_step() doesn't enter the sync
+    // barriers in the event of an overflow. Doing so will
+    // cause an assert that the current thread is not a
+    // concurrent GC thread.
+    CMRemarkTask remarkTask(this, active_workers, true /* is_serial*/);
     remarkTask.work(0);
   }
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
-  guarantee(satb_mq_set.completed_buffers_num() == 0, "invariant");
+  guarantee(has_overflown() ||
+            satb_mq_set.completed_buffers_num() == 0,
+            err_msg("Invariant: has_overflown = %s, num buffers = %d",
+                    BOOL_TO_STR(has_overflown()),
+                    satb_mq_set.completed_buffers_num()));
 
   print_stats();
-
-#if VERIFY_OBJS_PROCESSED
-  if (_scan_obj_cl.objs_processed != ThreadLocalObjQueue::objs_enqueued) {
-    gclog_or_tty->print_cr("Processed = %d, enqueued = %d.",
-                           _scan_obj_cl.objs_processed,
-                           ThreadLocalObjQueue::objs_enqueued);
-    guarantee(_scan_obj_cl.objs_processed ==
-              ThreadLocalObjQueue::objs_enqueued,
-              "Different number of objs processed and enqueued.");
-  }
-#endif
 }
 
 #ifndef PRODUCT
@@ -3233,6 +3281,13 @@
   }
 }
 
+void ConcurrentMark::print_on_error(outputStream* st) const {
+  st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT,
+      _prevMarkBitMap, _nextMarkBitMap);
+  _prevMarkBitMap->print_on_error(st, " Prev Bits: ");
+  _nextMarkBitMap->print_on_error(st, " Next Bits: ");
+}
+
 // We take a break if someone is trying to stop the world.
 bool ConcurrentMark::do_yield_check(uint worker_id) {
   if (should_yield()) {
@@ -3870,8 +3925,8 @@
 
 /*****************************************************************************
 
-    The do_marking_step(time_target_ms) method is the building block
-    of the parallel marking framework. It can be called in parallel
+    The do_marking_step(time_target_ms, ...) method is the building
+    block of the parallel marking framework. It can be called in parallel
     with other invocations of do_marking_step() on different tasks
     (but only one per task, obviously) and concurrently with the
     mutator threads, or during remark, hence it eliminates the need
@@ -3881,7 +3936,7 @@
     pauses too, since do_marking_step() ensures that it aborts before
     it needs to yield.
 
-    The data structures that is uses to do marking work are the
+    The data structures that it uses to do marking work are the
     following:
 
       (1) Marking Bitmap. If there are gray objects that appear only
@@ -3930,7 +3985,7 @@
       (2) When a global overflow (on the global stack) has been
       triggered. Before the task aborts, it will actually sync up with
       the other tasks to ensure that all the marking data structures
-      (local queues, stacks, fingers etc.)  are re-initialised so that
+      (local queues, stacks, fingers etc.)  are re-initialized so that
       when do_marking_step() completes, the marking phase can
       immediately restart.
 
@@ -3967,11 +4022,25 @@
     place, it was natural to piggy-back all the other conditions on it
     too and not constantly check them throughout the code.
 
+    If do_termination is true then do_marking_step will enter its
+    termination protocol.
+
+    The value of is_serial must be true when do_marking_step is being
+    called serially (i.e. by the VMThread) and do_marking_step should
+    skip any synchronization in the termination and overflow code.
+    Examples include the serial remark code and the serial reference
+    processing closures.
+
+    The value of is_serial must be false when do_marking_step is
+    being called by any of the worker threads in a work gang.
+    Examples include the concurrent marking code (CMMarkingTask),
+    the MT remark code, and the MT reference processing closures.
+
  *****************************************************************************/
 
 void CMTask::do_marking_step(double time_target_ms,
-                             bool do_stealing,
-                             bool do_termination) {
+                             bool do_termination,
+                             bool is_serial) {
   assert(time_target_ms >= 1.0, "minimum granularity is 1ms");
   assert(concurrent() == _cm->concurrent(), "they should be the same");
 
@@ -3992,6 +4061,12 @@
   _start_time_ms = os::elapsedVTime() * 1000.0;
   statsOnly( _interval_start_time_ms = _start_time_ms );
 
+  // If do_stealing is true then do_marking_step will attempt to
+  // steal work from the other CMTasks. It only makes sense to
+  // enable stealing when the termination protocol is enabled
+  // and do_marking_step() is not being called serially.
+  bool do_stealing = do_termination && !is_serial;
+
   double diff_prediction_ms =
     g1_policy->get_new_prediction(&_marking_step_diffs_ms);
   _time_target_ms = time_target_ms - diff_prediction_ms;
@@ -4111,7 +4186,7 @@
         // bitmap knows by how much we need to move it as it knows its
         // granularity).
         assert(_finger < _region_limit, "invariant");
-        HeapWord* new_finger = _nextMarkBitMap->nextWord(_finger);
+        HeapWord* new_finger = _nextMarkBitMap->nextObject(_finger);
         // Check if bitmap iteration was aborted while scanning the last object
         if (new_finger >= _region_limit) {
           giveup_current_region();
@@ -4253,10 +4328,12 @@
     }
 
     _termination_start_time_ms = os::elapsedVTime() * 1000.0;
+
     // The CMTask class also extends the TerminatorTerminator class,
     // hence its should_exit_termination() method will also decide
     // whether to exit the termination protocol or not.
-    bool finished = _cm->terminator()->offer_termination(this);
+    bool finished = (is_serial ||
+                     _cm->terminator()->offer_termination(this));
     double termination_end_time_ms = os::elapsedVTime() * 1000.0;
     _termination_time_ms +=
       termination_end_time_ms - _termination_start_time_ms;
@@ -4336,20 +4413,28 @@
         gclog_or_tty->print_cr("[%u] detected overflow", _worker_id);
       }
 
-      _cm->enter_first_sync_barrier(_worker_id);
-      // When we exit this sync barrier we know that all tasks have
-      // stopped doing marking work. So, it's now safe to
-      // re-initialise our data structures. At the end of this method,
-      // task 0 will clear the global data structures.
+      if (!is_serial) {
+        // We only need to enter the sync barrier if being called
+        // from a parallel context
+        _cm->enter_first_sync_barrier(_worker_id);
+
+        // When we exit this sync barrier we know that all tasks have
+        // stopped doing marking work. So, it's now safe to
+        // re-initialise our data structures. At the end of this method,
+        // task 0 will clear the global data structures.
+      }
 
       statsOnly( ++_aborted_overflow );
 
       // We clear the local state of this task...
       clear_region_fields();
 
-      // ...and enter the second barrier.
-      _cm->enter_second_sync_barrier(_worker_id);
-      // At this point everything has bee re-initialised and we're
+      if (!is_serial) {
+        // ...and enter the second barrier.
+        _cm->enter_second_sync_barrier(_worker_id);
+      }
+      // At this point, if we're during the concurrent phase of
+      // marking, everything has been re-initialized and we're
       // ready to restart.
     }
 
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -97,7 +97,6 @@
                                        HeapWord* limit = NULL) const;
 
   // conversion utilities
-  // XXX Fix these so that offsets are size_t's...
   HeapWord* offsetToHeapWord(size_t offset) const {
     return _bmStartWord + (offset << _shifter);
   }
@@ -105,10 +104,17 @@
     return pointer_delta(addr, _bmStartWord) >> _shifter;
   }
   int heapWordDiffToOffsetDiff(size_t diff) const;
-  HeapWord* nextWord(HeapWord* addr) {
-    return offsetToHeapWord(heapWordToOffset(addr) + 1);
+
+  // The argument addr should be the start address of a valid object
+  HeapWord* nextObject(HeapWord* addr) {
+    oop obj = (oop) addr;
+    HeapWord* res =  addr + obj->size();
+    assert(offsetToHeapWord(heapWordToOffset(res)) == res, "sanity");
+    return res;
   }
 
+  void print_on_error(outputStream* st, const char* prefix) const;
+
   // debugging
   NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
 };
@@ -162,7 +168,7 @@
 class CMMarkStack VALUE_OBJ_CLASS_SPEC {
   VirtualSpace _virtual_space;   // Underlying backing store for actual stack
   ConcurrentMark* _cm;
-  oop*   _base;        // bottom of stack
+  oop* _base;        // bottom of stack
   jint _index;       // one more than last occupied index
   jint _capacity;    // max #elements
   jint _saved_index; // value of _index saved at start of GC
@@ -487,9 +493,12 @@
   // structures are initialised to a sensible and predictable state.
   void set_non_marking_state();
 
+  // Called to indicate how many threads are currently active.
+  void set_concurrency(uint active_tasks);
+
   // It should be called to indicate which phase we're in (concurrent
   // mark or remark) and how many threads are currently active.
-  void set_phase(uint active_tasks, bool concurrent);
+  void set_concurrency_and_phase(uint active_tasks, bool concurrent);
 
   // prints all gathered CM-related statistics
   void print_stats();
@@ -822,6 +831,8 @@
 
   void print_worker_threads_on(outputStream* st) const;
 
+  void print_on_error(outputStream* st) const;
+
   // The following indicate whether a given verbose level has been
   // set. Notice that anything above stats is conditional to
   // _MARKING_VERBOSE_ having been set to 1
@@ -1142,7 +1153,9 @@
   // trying not to exceed the given duration. However, it might exit
   // prematurely, according to some conditions (i.e. SATB buffers are
   // available for processing).
-  void do_marking_step(double target_ms, bool do_stealing, bool do_termination);
+  void do_marking_step(double target_ms,
+                       bool do_termination,
+                       bool is_serial);
 
   // These two calls start and stop the timer
   void record_start_time() {
--- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -252,12 +252,10 @@
 
     start_offset = _bm.get_next_one_offset(start_offset, end_offset);
     while (start_offset < end_offset) {
-      HeapWord* obj_addr = offsetToHeapWord(start_offset);
-      oop obj = (oop) obj_addr;
       if (!cl->do_bit(start_offset)) {
         return false;
       }
-      HeapWord* next_addr = MIN2(obj_addr + obj->size(), end_addr);
+      HeapWord* next_addr = MIN2(nextObject(offsetToHeapWord(start_offset)), end_addr);
       BitMap::idx_t next_offset = heapWordToOffset(next_addr);
       start_offset = _bm.get_next_one_offset(next_offset, end_offset);
     }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -854,7 +854,8 @@
   assert(!isHumongous(word_size), "we do not allow humongous TLABs");
 
   unsigned int dummy_gc_count_before;
-  return attempt_allocation(word_size, &dummy_gc_count_before);
+  int dummy_gclocker_retry_count = 0;
+  return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count);
 }
 
 HeapWord*
@@ -863,14 +864,14 @@
   assert_heap_not_locked_and_not_at_safepoint();
 
   // Loop until the allocation is satisified, or unsatisfied after GC.
-  for (int try_count = 1; /* we'll return */; try_count += 1) {
+  for (int try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
     unsigned int gc_count_before;
 
     HeapWord* result = NULL;
     if (!isHumongous(word_size)) {
-      result = attempt_allocation(word_size, &gc_count_before);
+      result = attempt_allocation(word_size, &gc_count_before, &gclocker_retry_count);
     } else {
-      result = attempt_allocation_humongous(word_size, &gc_count_before);
+      result = attempt_allocation_humongous(word_size, &gc_count_before, &gclocker_retry_count);
     }
     if (result != NULL) {
       return result;
@@ -894,6 +895,9 @@
       }
       return result;
     } else {
+      if (gclocker_retry_count > GCLockerRetryAllocationCount) {
+        return NULL;
+      }
       assert(op.result() == NULL,
              "the result should be NULL if the VM op did not succeed");
     }
@@ -910,7 +914,8 @@
 }
 
 HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
-                                           unsigned int *gc_count_before_ret) {
+                                           unsigned int *gc_count_before_ret,
+                                           int* gclocker_retry_count_ret) {
   // Make sure you read the note in attempt_allocation_humongous().
 
   assert_heap_not_locked_and_not_at_safepoint();
@@ -986,10 +991,16 @@
         return NULL;
       }
     } else {
+      if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
+        MutexLockerEx x(Heap_lock);
+        *gc_count_before_ret = total_collections();
+        return NULL;
+      }
       // The GCLocker is either active or the GCLocker initiated
       // GC has not yet been performed. Stall until it is and
       // then retry the allocation.
       GC_locker::stall_until_clear();
+      (*gclocker_retry_count_ret) += 1;
     }
 
     // We can reach here if we were unsuccessul in scheduling a
@@ -1019,7 +1030,8 @@
 }
 
 HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
-                                          unsigned int * gc_count_before_ret) {
+                                          unsigned int * gc_count_before_ret,
+                                          int* gclocker_retry_count_ret) {
   // The structure of this method has a lot of similarities to
   // attempt_allocation_slow(). The reason these two were not merged
   // into a single one is that such a method would require several "if
@@ -1104,10 +1116,16 @@
         return NULL;
       }
     } else {
+      if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
+        MutexLockerEx x(Heap_lock);
+        *gc_count_before_ret = total_collections();
+        return NULL;
+      }
       // The GCLocker is either active or the GCLocker initiated
       // GC has not yet been performed. Stall until it is and
       // then retry the allocation.
       GC_locker::stall_until_clear();
+      (*gclocker_retry_count_ret) += 1;
     }
 
     // We can reach here if we were unsuccessul in scheduling a
@@ -3280,12 +3298,12 @@
 
 void G1CollectedHeap::verify(bool silent,
                              VerifyOption vo) {
-  if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
+  if (SafepointSynchronize::is_at_safepoint()) {
     if (!silent) { gclog_or_tty->print("Roots "); }
     VerifyRootsClosure rootsCl(vo);
 
     assert(Thread::current()->is_VM_thread(),
-      "Expected to be executed serially by the VM thread at this point");
+           "Expected to be executed serially by the VM thread at this point");
 
     CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false);
     VerifyKlassClosure klassCl(this, &rootsCl);
@@ -3370,7 +3388,8 @@
     }
     guarantee(!failures, "there should not have been any failures");
   } else {
-    if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) ");
+    if (!silent)
+      gclog_or_tty->print("(SKIPPING roots, heapRegionSets, heapRegions, remset) ");
   }
 }
 
@@ -3418,6 +3437,15 @@
   heap_region_iterate(&blk);
 }
 
+void G1CollectedHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+  if (_cm != NULL) {
+    st->cr();
+    _cm->print_on_error(st);
+  }
+}
+
 void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     workers()->print_worker_threads_on(st);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -559,18 +559,21 @@
   // the mutator alloc region without taking the Heap_lock. This
   // should only be used for non-humongous allocations.
   inline HeapWord* attempt_allocation(size_t word_size,
-                                      unsigned int* gc_count_before_ret);
+                                      unsigned int* gc_count_before_ret,
+                                      int* gclocker_retry_count_ret);
 
   // Second-level mutator allocation attempt: take the Heap_lock and
   // retry the allocation attempt, potentially scheduling a GC
   // pause. This should only be used for non-humongous allocations.
   HeapWord* attempt_allocation_slow(size_t word_size,
-                                    unsigned int* gc_count_before_ret);
+                                    unsigned int* gc_count_before_ret,
+                                    int* gclocker_retry_count_ret);
 
   // Takes the Heap_lock and attempts a humongous allocation. It can
   // potentially schedule a GC pause.
   HeapWord* attempt_allocation_humongous(size_t word_size,
-                                         unsigned int* gc_count_before_ret);
+                                         unsigned int* gc_count_before_ret,
+                                         int* gclocker_retry_count_ret);
 
   // Allocation attempt that should be called during safepoints (e.g.,
   // at the end of a successful GC). expect_null_mutator_alloc_region
@@ -1578,6 +1581,7 @@
   virtual void verify(bool silent);
   virtual void print_on(outputStream* st) const;
   virtual void print_extended_on(outputStream* st) const;
+  virtual void print_on_error(outputStream* st) const;
 
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -60,7 +60,8 @@
 
 inline HeapWord*
 G1CollectedHeap::attempt_allocation(size_t word_size,
-                                    unsigned int* gc_count_before_ret) {
+                                    unsigned int* gc_count_before_ret,
+                                    int* gclocker_retry_count_ret) {
   assert_heap_not_locked_and_not_at_safepoint();
   assert(!isHumongous(word_size), "attempt_allocation() should not "
          "be called for humongous allocation requests");
@@ -68,7 +69,9 @@
   HeapWord* result = _mutator_alloc_region.attempt_allocation(word_size,
                                                       false /* bot_updates */);
   if (result == NULL) {
-    result = attempt_allocation_slow(word_size, gc_count_before_ret);
+    result = attempt_allocation_slow(word_size,
+                                     gc_count_before_ret,
+                                     gclocker_retry_count_ret);
   }
   assert_heap_not_locked();
   if (result != NULL) {
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1359,18 +1359,6 @@
 #endif // PRODUCT
 }
 
-#ifndef PRODUCT
-// for debugging, bit of a hack...
-static char*
-region_num_to_mbs(int length) {
-  static char buffer[64];
-  double bytes = (double) (length * HeapRegion::GrainBytes);
-  double mbs = bytes / (double) (1024 * 1024);
-  sprintf(buffer, "%7.2lfMB", mbs);
-  return buffer;
-}
-#endif // PRODUCT
-
 uint G1CollectorPolicy::max_regions(int purpose) {
   switch (purpose) {
     case GCAllocForSurvived:
@@ -1806,6 +1794,14 @@
 }
 #endif // !PRODUCT
 
+double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) {
+  // Returns the given amount of reclaimable bytes (that represents
+  // the amount of reclaimable space still to be collected) as a
+  // percentage of the current heap capacity.
+  size_t capacity_bytes = _g1->capacity();
+  return (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
+}
+
 bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
                                                 const char* false_action_str) {
   CollectionSetChooser* cset_chooser = _collectionSetChooser;
@@ -1815,19 +1811,21 @@
                   ergo_format_reason("candidate old regions not available"));
     return false;
   }
+
+  // Is the amount of uncollected reclaimable space above G1HeapWastePercent?
   size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
-  size_t capacity_bytes = _g1->capacity();
-  double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
+  double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
   double threshold = (double) G1HeapWastePercent;
-  if (perc < threshold) {
+  if (reclaimable_perc <= threshold) {
     ergo_verbose4(ErgoMixedGCs,
               false_action_str,
-              ergo_format_reason("reclaimable percentage lower than threshold")
+              ergo_format_reason("reclaimable percentage not over threshold")
               ergo_format_region("candidate old regions")
               ergo_format_byte_perc("reclaimable")
               ergo_format_perc("threshold"),
               cset_chooser->remaining_regions(),
-              reclaimable_bytes, perc, threshold);
+              reclaimable_bytes,
+              reclaimable_perc, threshold);
     return false;
   }
 
@@ -1838,10 +1836,50 @@
                 ergo_format_byte_perc("reclaimable")
                 ergo_format_perc("threshold"),
                 cset_chooser->remaining_regions(),
-                reclaimable_bytes, perc, threshold);
+                reclaimable_bytes,
+                reclaimable_perc, threshold);
   return true;
 }
 
+uint G1CollectorPolicy::calc_min_old_cset_length() {
+  // The min old CSet region bound is based on the maximum desired
+  // number of mixed GCs after a cycle. I.e., even if some old regions
+  // look expensive, we should add them to the CSet anyway to make
+  // sure we go through the available old regions in no more than the
+  // maximum desired number of mixed GCs.
+  //
+  // The calculation is based on the number of marked regions we added
+  // to the CSet chooser in the first place, not how many remain, so
+  // that the result is the same during all mixed GCs that follow a cycle.
+
+  const size_t region_num = (size_t) _collectionSetChooser->length();
+  const size_t gc_num = (size_t) MAX2(G1MixedGCCountTarget, (uintx) 1);
+  size_t result = region_num / gc_num;
+  // emulate ceiling
+  if (result * gc_num < region_num) {
+    result += 1;
+  }
+  return (uint) result;
+}
+
+uint G1CollectorPolicy::calc_max_old_cset_length() {
+  // The max old CSet region bound is based on the threshold expressed
+  // as a percentage of the heap size. I.e., it should bound the
+  // number of old regions added to the CSet irrespective of how many
+  // of them are available.
+
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  const size_t region_num = g1h->n_regions();
+  const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
+  size_t result = region_num * perc / 100;
+  // emulate ceiling
+  if (100 * result < region_num * perc) {
+    result += 1;
+  }
+  return (uint) result;
+}
+
+
 void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
   double young_start_time_sec = os::elapsedTime();
 
@@ -1855,7 +1893,7 @@
 
   double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
   double predicted_pause_time_ms = base_time_ms;
-  double time_remaining_ms = target_pause_time_ms - base_time_ms;
+  double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
 
   ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
                 "start choosing CSet",
@@ -1893,7 +1931,7 @@
 
   _collection_set = _inc_cset_head;
   _collection_set_bytes_used_before = _inc_cset_bytes_used_before;
-  time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms;
+  time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0);
   predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
 
   ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
@@ -1917,8 +1955,8 @@
   if (!gcs_are_young()) {
     CollectionSetChooser* cset_chooser = _collectionSetChooser;
     cset_chooser->verify();
-    const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length();
-    const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length();
+    const uint min_old_cset_length = calc_min_old_cset_length();
+    const uint max_old_cset_length = calc_max_old_cset_length();
 
     uint expensive_region_num = 0;
     bool check_time_remaining = adaptive_young_list_length();
@@ -1936,6 +1974,30 @@
         break;
       }
 
+
+      // Stop adding regions if the remaining reclaimable space is
+      // not above G1HeapWastePercent.
+      size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
+      double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
+      double threshold = (double) G1HeapWastePercent;
+      if (reclaimable_perc <= threshold) {
+        // We've added enough old regions that the amount of uncollected
+        // reclaimable space is at or below the waste threshold. Stop
+        // adding old regions to the CSet.
+        ergo_verbose5(ErgoCSetConstruction,
+                      "finish adding old regions to CSet",
+                      ergo_format_reason("reclaimable percentage not over threshold")
+                      ergo_format_region("old")
+                      ergo_format_region("max")
+                      ergo_format_byte_perc("reclaimable")
+                      ergo_format_perc("threshold"),
+                      old_cset_region_length(),
+                      max_old_cset_length,
+                      reclaimable_bytes,
+                      reclaimable_perc, threshold);
+        break;
+      }
+
       double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
       if (check_time_remaining) {
         if (predicted_time_ms > time_remaining_ms) {
@@ -1975,7 +2037,7 @@
       }
 
       // We will add this region to the CSet.
-      time_remaining_ms -= predicted_time_ms;
+      time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
       predicted_pause_time_ms += predicted_time_ms;
       cset_chooser->remove_and_move_to_next(hr);
       _g1->old_set_remove(hr);
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -619,6 +619,18 @@
   bool predict_will_fit(uint young_length, double base_time_ms,
                         uint base_free_regions, double target_pause_time_ms);
 
+  // Calculate the minimum number of old regions we'll add to the CSet
+  // during a mixed GC.
+  uint calc_min_old_cset_length();
+
+  // Calculate the maximum number of old regions we'll add to the CSet
+  // during a mixed GC.
+  uint calc_max_old_cset_length();
+
+  // Returns the given amount of uncollected reclaimable space
+  // as a percentage of the current heap capacity.
+  double reclaimable_bytes_perc(size_t reclaimable_bytes);
+
 public:
 
   G1CollectorPolicy();
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -53,15 +53,6 @@
 }
 
 
-static int byte_index_to_index(int ind) {
-  assert((ind % oopSize) == 0, "Invariant.");
-  return ind / oopSize;
-}
-
-static int index_to_byte_index(int byte_ind) {
-  return byte_ind * oopSize;
-}
-
 void PtrQueue::enqueue_known_active(void* ptr) {
   assert(0 <= _index && _index <= _sz, "Invariant.");
   assert(_index == 0 || _buf != NULL, "invariant");
--- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -373,6 +373,8 @@
                          " does not exceed used.end() = " PTR_FORMAT ","
                          " yet last_chunk_index_to_check " INTPTR_FORMAT
                          " exceeds last_chunk_index " INTPTR_FORMAT,
+                         last_block, last_block + last_block_size,
+                         used.end(),
                          last_chunk_index_to_check, last_chunk_index));
           assert(sp->used_region().end() > used.end(),
                  err_msg("Expansion did not happen: "
--- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -173,6 +173,12 @@
   void reset_counters();
 #endif  // #ifndef PRODUCT
 
+  void print_on_error(outputStream* st) const {
+    st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this);
+    _beg_bits.print_on_error(st, " Begin Bits: ");
+    _end_bits.print_on_error(st, " End Bits:   ");
+  }
+
 #ifdef  ASSERT
   void verify_clear() const;
   inline void verify_bit(idx_t bit) const;
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -326,6 +326,7 @@
 
   uint loop_count = 0;
   uint gc_count = 0;
+  int gclocker_stalled_count = 0;
 
   while (result == NULL) {
     // We don't want to have multiple collections for a single filled generation.
@@ -354,6 +355,10 @@
         return result;
       }
 
+      if (gclocker_stalled_count > GCLockerRetryAllocationCount) {
+        return NULL;
+      }
+
       // Failed to allocate without a gc.
       if (GC_locker::is_active_and_needs_gc()) {
         // If this thread is not in a jni critical section, we stall
@@ -366,6 +371,7 @@
         if (!jthr->in_critical()) {
           MutexUnlocker mul(Heap_lock);
           GC_locker::stall_until_clear();
+          gclocker_stalled_count += 1;
           continue;
         } else {
           if (CheckJNICalls) {
@@ -409,7 +415,7 @@
         // heap remains parsable.
         const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
         const bool softrefs_clear = collector_policy()->all_soft_refs_clear();
-        assert(!limit_exceeded || softrefs_clear, "Should have been cleared");
+
         if (limit_exceeded && softrefs_clear) {
           *gc_overhead_limit_was_exceeded = true;
           size_policy()->set_gc_overhead_limit_exceeded(false);
@@ -642,6 +648,15 @@
   MetaspaceAux::print_on(st);
 }
 
+void ParallelScavengeHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+  if (UseParallelOldGC) {
+    st->cr();
+    PSParallelCompact::print_on_error(st);
+  }
+}
+
 void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const {
   PSScavenge::gc_task_manager()->threads_do(tc);
 }
@@ -656,7 +671,7 @@
     tty->print_cr("[Accumulated GC generation 0 time %3.7f secs]", time);
   }
   if (TraceGen1Time) {
-    double time = PSMarkSweep::accumulated_time()->seconds();
+    double time = UseParallelOldGC ? PSParallelCompact::accumulated_time()->seconds() : PSMarkSweep::accumulated_time()->seconds();
     tty->print_cr("[Accumulated GC generation 1 time %3.7f secs]", time);
   }
 }
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -220,6 +220,7 @@
 
   void prepare_for_verify();
   virtual void print_on(outputStream* st) const;
+  virtual void print_on_error(outputStream* st) const;
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
   virtual void print_tracing_info() const;
--- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -256,7 +256,7 @@
   }
 
   if (PrintGC && Verbose) {
-    if (success && GC_locker::is_active()) {
+    if (success && GC_locker::is_active_and_needs_gc()) {
       gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
     }
   }
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -165,6 +165,10 @@
 #endif  // #ifdef ASSERT
 
 
+void PSParallelCompact::print_on_error(outputStream* st) {
+  _mark_bitmap.print_on_error(st);
+}
+
 #ifndef PRODUCT
 const char* PSParallelCompact::space_names[] = {
   "old ", "eden", "from", "to  "
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1163,6 +1163,8 @@
   // Time since last full gc (in milliseconds).
   static jlong millis_since_last_gc();
 
+  static void print_on_error(outputStream* st);
+
 #ifndef PRODUCT
   // Debugging support.
   static const char* space_names[last_space_id];
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -948,6 +948,8 @@
       break;
     }
     if (e != scan_end) {
+      assert(e < scan_end, err_msg("e: " PTR_FORMAT " scan_end: " PTR_FORMAT, e, scan_end));
+
       if ((page_expected.size != page_size || page_expected.lgrp_id != lgrp_id())
           && page_expected.size != 0) {
         os::free_memory(s, pointer_delta(e, s, sizeof(char)), page_size);
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -567,6 +567,14 @@
     print_on(st);
   }
 
+  virtual void print_on_error(outputStream* st) const {
+    st->print_cr("Heap:");
+    print_extended_on(st);
+    st->cr();
+
+    _barrier_set->print_on(st);
+  }
+
   // Print all GC threads (other than the VM thread)
   // used by this heap.
   virtual void print_gc_threads_on(outputStream* st) const = 0;
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -236,7 +236,7 @@
     for (jint i = 0; i < values->length(); i++) {
       ScopeValue* cur_second = NULL;
       ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second, oop_recorder);
-      
+
       if (isLongArray && cur_second == NULL) {
         // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
         // add an int 0 constant
@@ -294,10 +294,14 @@
       if (!assumption.is_null()) {
         if (assumption->klass() == Assumptions_MethodContents::klass()) {
           assumption_MethodContents(assumption);
+        } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
+          assumption_NoFinalizableSubclass(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
           assumption_ConcreteSubtype(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
           assumption_ConcreteMethod(assumption);
+        } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
+          assumption_CallSiteTargetValue(assumption);
         } else {
           assumption->print();
           fatal("unexpected Assumption subclass");
@@ -350,7 +354,7 @@
 // constructor used to create a stub
 CodeInstaller::CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id) {
   No_Safepoint_Verifier no_safepoint;
-  
+
   _oop_recorder = new OopRecorder(&_arena);
   initialize_fields(target_method(), NULL);
   assert(_name != NULL, "installMethod needs NON-NULL name");
@@ -398,7 +402,7 @@
 
   _debug_recorder = new DebugInformationRecorder(_oop_recorder);
   _debug_recorder->set_oopmaps(new OopMapSet());
-  
+
   buffer.initialize_oop_recorder(_oop_recorder);
 
   _instructions = buffer.insts();
@@ -416,9 +420,17 @@
     if (site->is_a(CompilationResult_Call::klass())) {
       TRACE_graal_4("call at %i", pc_offset);
       site_Call(buffer, pc_offset, site);
-    } else if (site->is_a(CompilationResult_Safepoint::klass())) {
-      TRACE_graal_4("safepoint at %i", pc_offset);
-      site_Safepoint(buffer, pc_offset, site);
+    } else if (site->is_a(CompilationResult_Infopoint::klass())) {
+      // three reasons for infopoints denote actual safepoints
+      oop reason = CompilationResult_Infopoint::reason(site);
+      if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+        TRACE_graal_4("safepoint at %i", pc_offset);
+        site_Safepoint(buffer, pc_offset, site);
+      } else {
+        // if the infopoint is not an actual safepoint, it must have one of the other reasons
+        // (safeguard against new safepoint types that require handling above)
+        assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, "");
+      }
     } else if (site->is_a(CompilationResult_DataPatch::klass())) {
       TRACE_graal_4("datapatch at %i", pc_offset);
       site_DataPatch(buffer, pc_offset, site);
@@ -437,6 +449,12 @@
   _dependencies->assert_evol_method(method());
 }
 
+void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) {
+  Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption());
+  Klass* receiverType = asKlass(HotSpotResolvedObjectType::metaspaceKlass(receiverType_handle));
+  _dependencies->assert_has_no_finalizable_subclasses(receiverType);
+}
+
 void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) {
   Handle context_handle = Assumptions_ConcreteSubtype::context(assumption());
   Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption());
@@ -460,6 +478,13 @@
   _dependencies->assert_unique_concrete_method(context, impl());
 }
 
+void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) {
+  Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption());
+  Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption());
+
+  _dependencies->assert_call_site_target_value(callSite(), methodHandle());
+}
+
 void CodeInstaller::process_exception_handlers() {
   // allocate some arrays for use by the collection code.
   const int num_handlers = 5;
@@ -578,7 +603,7 @@
 }
 
 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
-  oop debug_info = CompilationResult_Safepoint::debugInfo(site);
+  oop debug_info = CompilationResult_Infopoint::debugInfo(site);
   assert(debug_info != NULL, "debug info expected");
 
   // address instruction = _instructions->start() + pc_offset;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -93,8 +93,10 @@
   void initialize_buffer(CodeBuffer& buffer);
 
   void assumption_MethodContents(Handle assumption);
+  void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
   void assumption_ConcreteMethod(Handle assumption);
+  void assumption_CallSiteTargetValue(Handle assumption);
 
   void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site);
   void site_Call(CodeBuffer& buffer, jint pc_offset, oop site);
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -91,6 +91,10 @@
       VMToCompiler::startCompiler();
       _initialized = true;
       if (BootstrapGraal) {
+        // We turn off CompileTheWorld and complete the VM startup so that
+        // Graal can be compiled by C1/C2 when we do a CTW.
+        NOT_PRODUCT(CompileTheWorld = false);
+        CompilationPolicy::completed_vm_startup();
         VMToCompiler::bootstrap();
       }
     }
--- a/src/share/vm/graal/graalCompiler.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -68,7 +68,7 @@
 
   // Print compilation timers and statistics
   virtual void print_timers();
-  
+
   static Handle get_JavaTypeFromSignature(Symbol* signature, KlassHandle accessor, TRAPS);
   static Handle get_JavaType(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS);
   static Handle get_JavaType(Symbol* klass_name, TRAPS);
@@ -93,6 +93,26 @@
     return ((index & 0xFF) << 8) | (index >> 8);
   }
 
+  static int to_index_u4(int index) {
+    // Swap.
+    return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24);
+  }
+
+  static int to_cp_index(int raw_index, Bytecodes::Code bc) {
+    int cp_index;
+    if (bc == Bytecodes::_invokedynamic) {
+      cp_index = to_index_u4(raw_index);
+      assert(ConstantPool::is_invokedynamic_index(cp_index), "not an invokedynamic constant pool index");
+    } else {
+      assert(bc == Bytecodes::_getfield        || bc == Bytecodes::_putfield  ||
+             bc == Bytecodes::_getstatic       || bc == Bytecodes::_putstatic ||
+             bc == Bytecodes::_invokeinterface || bc == Bytecodes::_invokevirtual ||
+             bc == Bytecodes::_invokespecial   || bc == Bytecodes::_invokestatic, err_msg("unexpected invoke opcode: %d %s", bc, Bytecodes::name(bc)));
+      cp_index = to_cp_index_u2(raw_index);
+    }
+    return cp_index;
+  }
+
   static void initialize_buffer_blob();
 };
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -62,7 +62,7 @@
 C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result))
   methodHandle method = asMethod(metaspace_method);
   ResourceMark rm;
-  
+
   int code_size = method->code_size();
   jbyte* reconstituted_code = NULL;
 
@@ -320,6 +320,11 @@
   return code == NULL ? 0 : code->insts_size();
 C2V_END
 
+C2V_VMENTRY(jint, constantPoolLength, (JNIEnv *env, jobject, jobject type))
+  ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
+  return cp->length();
+C2V_END
+
 C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve))
   ResourceMark rm;
 
@@ -416,12 +421,22 @@
   return JNIHandles::make_local(THREAD, result);
 C2V_END
 
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode))
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  index = GraalCompiler::to_cp_index(index, bc);
+  constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants());
+  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, index);
+
+  return JNIHandles::make_local(THREAD, appendix_oop);
+C2V_END
+
 C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode))
-  index = GraalCompiler::to_cp_index_u2(index);
   constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
   instanceKlassHandle pool_holder(cp->pool_holder());
 
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  index = GraalCompiler::to_cp_index(index, bc);
+
   methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder);
   if (!method.is_null()) {
     Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL);
@@ -430,8 +445,13 @@
     // Get the method's name and signature.
     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);
+    Handle type;
+    if (bc != Bytecodes::_invokedynamic) {
+      int holder_index = cp->klass_ref_index_at(index);
+      type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
+    } else {
+      type = Handle(SystemDictionary::MethodHandle_klass()->java_mirror());
+    }
     return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD));
   }
 C2V_END
@@ -445,11 +465,11 @@
 
 C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op))
   ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
-  int opcode = (op & 0xFF);
-  if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray
-      && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w)
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF);
+  if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray
+      && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w)
   {
-    index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index));
+    index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index(index, bc));
   }
   constantTag tag = cp->tag_at(index);
   if (tag.is_field_or_method()) {
@@ -479,7 +499,7 @@
   int holder_index = cp->klass_ref_index_at(index);
   Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
   instanceKlassHandle holder_klass;
-  
+
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   int offset = -1;
   AccessFlags flags;
@@ -499,7 +519,7 @@
       holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL);
     }
   }
-  
+
   Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL);
   Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD);
 
@@ -606,6 +626,11 @@
 #endif
   set_boolean("verifyOops", VerifyOops);
   set_boolean("ciTime", CITime);
+  set_boolean("compileTheWorld", CompileTheWorld);
+  set_int("compileTheWorldStartAt", CompileTheWorldStartAt);
+  set_int("compileTheWorldStopAt", CompileTheWorldStopAt);
+  set_boolean("printCompilation", PrintCompilation);
+  set_boolean("printInlining", PrintInlining);
   set_boolean("useFastLocking", GraalUseFastLocking);
   set_boolean("useBiasedLocking", UseBiasedLocking);
   set_boolean("usePopCountInstruction", UsePopCountInstruction);
@@ -640,6 +665,7 @@
   set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset()));
   set_int("extraStackEntries", Method::extra_stack_entries());
   set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
+  set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes());
   set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER);
   set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
@@ -663,7 +689,7 @@
   set_int("arrayKlassLayoutHelperIdentifier", 0x80000000);
   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()));
 
@@ -763,6 +789,13 @@
   set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret);
   set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant);
   set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable);
+
+  set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic);
+  set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual);
+  set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic);
+  set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
+  set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
+
   set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
   set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
   set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
@@ -882,23 +915,17 @@
   return JNIHandles::make_local(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args))
+C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod))
   ResourceMark rm;
   HandleMark hm;
 
-  assert(metaspace_method != 0, "just checking");
-  methodHandle mh = asMethod(metaspace_method);
+  nmethod* nm = (nmethod*) (address) nativeMethod;
+  methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
 
   JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
   JavaValue result(jap.get_ret_type());
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
   jca.set_alternative_target(nm);
   JavaCalls::call(&result, mh, &jca, CHECK_NULL);
 
@@ -912,29 +939,6 @@
   }
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3))
-  ResourceMark rm;
-  HandleMark hm;
-
-  methodHandle method = asMethod(metaspace_method);
-  assert(!method.is_null(), "just checking");
-  JavaValue result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_oop(JNIHandles::resolve(arg1));
-  args.push_oop(JNIHandles::resolve(arg2));
-  args.push_oop(JNIHandles::resolve(arg3));
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
-  args.set_alternative_target(nm);
-  JavaCalls::call(&result, method, &args, CHECK_NULL);
-
-  return JNIHandles::make_local((oop) result.get_jobject());
-C2V_END
-
 C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method))
 
   Method* method = asMethod(metaspace_method);
@@ -1005,10 +1009,10 @@
     u2 typeCPIdx = table[i].descriptor_cp_index;
     u2 slot = table[i].slot;
 
-    char* name = method->constants()->string_at_noresolve(nameCPIdx);
+    char* name = method->constants()->symbol_at(nameCPIdx)->as_C_string();
     Handle nameHandle = java_lang_String::create_from_str(name, CHECK_NULL);
 
-    char* typeInfo = method->constants()->string_at_noresolve(typeCPIdx);
+    char* typeInfo = method->constants()->symbol_at(typeCPIdx)->as_C_string();
     Handle typeHandle = java_lang_String::create_from_str(typeInfo, CHECK_NULL);
 
     Handle holderHandle = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0);
@@ -1053,6 +1057,20 @@
 C2V_END
 
 
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  if (!m->is_not_entrant()) {
+    m->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+C2V_END
+
+
+C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  return m->is_alive() && !m->is_not_entrant();
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1102,8 +1120,10 @@
   {CC"getInvocationCount",            CC"("METASPACE_METHOD")I",                                        FN_PTR(getInvocationCount)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
   {CC"getVtableEntryOffset",          CC"("METASPACE_METHOD")I",                                        FN_PTR(getVtableEntryOffset)},
+  {CC"constantPoolLength",            CC"("HS_RESOLVED_TYPE")I",                                        FN_PTR(constantPoolLength)},
   {CC"lookupType",                    CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupConstantInPool)},
+  {CC"lookupAppendixInPool",          CC"("HS_RESOLVED_TYPE"IB)"OBJECT,                                 FN_PTR(lookupAppendixInPool)},
   {CC"lookupMethodInPool",            CC"("HS_RESOLVED_TYPE"IB)"METHOD,                                 FN_PTR(lookupMethodInPool)},
   {CC"lookupTypeInPool",              CC"("HS_RESOLVED_TYPE"I)"TYPE,                                    FN_PTR(lookupTypeInPool)},
   {CC"lookupReferencedTypeInPool",    CC"("HS_RESOLVED_TYPE"IB)V",                                      FN_PTR(lookupReferencedTypeInPool)},
@@ -1121,14 +1141,15 @@
   {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"executeCompiledMethodVarargs",  CC"(["OBJECT NMETHOD")"OBJECT,                                    FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {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)},
   {CC"clearQueuedForCompilation",     CC"("HS_RESOLVED_METHOD")V",                                      FN_PTR(clearQueuedForCompilation)},
   {CC"reprofile",                     CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
+  {CC"invalidateInstalledCode",       CC"(J)V",                                                         FN_PTR(invalidateInstalledCode)},
+  {CC"isInstalledCodeValid",          CC"(J)Z",                                                         FN_PTR(isInstalledCodeValid)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalEnv.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -319,6 +319,19 @@
 methodHandle GraalEnv::get_method_by_index_impl(constantPoolHandle& cpool,
                                           int index, Bytecodes::Code bc,
                                           instanceKlassHandle& accessor) {
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+    bool is_resolved = !cpce->is_f1_null();
+    if (is_resolved) {
+      // Get the invoker Method* from the constant pool.
+      // (The appendix argument, if any, will be noted in the method's signature.)
+      Method* adapter = cpce->f1_as_method();
+      return methodHandle(adapter);
+    }
+
+    return NULL;
+  }
+
   int holder_index = cpool->klass_ref_index_at(index);
   bool holder_is_accessible;
   KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
@@ -327,6 +340,27 @@
   Symbol* name_sym = cpool->name_ref_at(index);
   Symbol* sig_sym  = cpool->signature_ref_at(index);
 
+  if (cpool->has_preresolution()
+      || (holder() == SystemDictionary::MethodHandle_klass() &&
+          MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    }
+  }
+
   if (holder_is_accessible) { // Our declared holder is loaded.
     instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
     methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
@@ -369,7 +403,6 @@
                                      int index, Bytecodes::Code bc,
                                      instanceKlassHandle& accessor) {
   ResourceMark rm;
-  assert(bc != Bytecodes::_invokedynamic, "invokedynamic not yet supported");
   return get_method_by_index_impl(cpool, index, bc, accessor);
 }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -110,6 +110,9 @@
   start_class(Assumptions_MethodContents)                                                                                                                      \
     oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                            \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
+    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                 \
+  end_class                                                                                                                                                    \
   start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
     oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
     oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
@@ -119,6 +122,10 @@
     oop_field(Assumptions_ConcreteMethod, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                             \
     oop_field(Assumptions_ConcreteMethod, impl, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                              \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_CallSiteTargetValue)                                                                                                                 \
+    oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljava/lang/invoke/CallSite;")                                                                        \
+    oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljava/lang/invoke/MethodHandle;")                                                                \
+  end_class                                                                                                                                                    \
   start_class(CompilationResult_Site)                                                                                                                          \
     int_field(CompilationResult_Site, pcOffset)                                                                                                                \
   end_class                                                                                                                                                    \
@@ -131,8 +138,18 @@
     int_field(CompilationResult_DataPatch, alignment)                                                                                                          \
     boolean_field(CompilationResult_DataPatch, inlined)                                                                                                        \
   end_class                                                                                                                                                    \
-  start_class(CompilationResult_Safepoint)                                                                                                                     \
-    oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+  start_class(InfopointReason)                                                                                                                                 \
+    static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                  \
+    static_oop_field(InfopointReason, SAFEPOINT, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                \
+    static_oop_field(InfopointReason, CALL, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                     \
+    static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Lcom/oracle/graal/api/code/InfopointReason;")                                                       \
+    static_oop_field(InfopointReason, METHOD_START, "Lcom/oracle/graal/api/code/InfopointReason;")                                                             \
+    static_oop_field(InfopointReason, METHOD_END, "Lcom/oracle/graal/api/code/InfopointReason;")                                                               \
+    static_oop_field(InfopointReason, LINE_NUMBER, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
+  end_class                                                                                                                                                    \
+  start_class(CompilationResult_Infopoint)                                                                                                                     \
+    oop_field(CompilationResult_Infopoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+    oop_field(CompilationResult_Infopoint, reason, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_ExceptionHandler)                                                                                                              \
     int_field(CompilationResult_ExceptionHandler, handlerPos)                                                                                                  \
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -85,6 +85,9 @@
     zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
     native,                                                     // native method
     native_synchronized,                                        // native method & is synchronized
+#ifdef GRAAL
+    execute_compiled_method,                                    // direct call to compiled method address
+#endif
     empty,                                                      // empty method (code: _return)
     accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
     abstract,                                                   // abstract method (throws an AbstractMethodException)
@@ -186,7 +189,8 @@
                                     int caller_actual_parameters,
                                     int callee_params,
                                     int callee_locals,
-                                    bool is_top_frame) {
+                                    bool is_top_frame,
+                                    bool is_bottom_frame) {
     return layout_activation(method,
                              temps,
                              popframe_args,
@@ -196,7 +200,8 @@
                              callee_locals,
                              (frame*)NULL,
                              (frame*)NULL,
-                             is_top_frame);
+                             is_top_frame,
+                             is_bottom_frame);
   }
 
   static int       layout_activation(Method* method,
@@ -208,7 +213,8 @@
                                      int callee_locals,
                                      frame* caller,
                                      frame* interpreter_frame,
-                                     bool is_top_frame);
+                                     bool is_top_frame,
+                                     bool is_bottom_frame);
 
   // Runtime support
   static bool       is_not_reached(                       methodHandle method, int bci);
--- a/src/share/vm/interpreter/interpreter.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -76,7 +76,7 @@
 
   if (PrintInterpreter) {
     st->cr();
-    Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_comments) NOT_DEBUG(CodeComments()));
+    Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_strings) NOT_DEBUG(CodeStrings()));
   }
 }
 
@@ -188,6 +188,13 @@
   // Method handle primitive?
   if (m->is_method_handle_intrinsic()) {
     vmIntrinsics::ID id = m->intrinsic_id();
+#ifdef GRAAL
+    if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+      // Special method kind for directly executing the verified entry point
+      // of a given nmethod.
+      return AbstractInterpreter::execute_compiled_method;
+    }
+#endif
     assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic");
     MethodKind kind = (MethodKind)( method_handle_invoke_FIRST +
                                     ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) );
@@ -287,6 +294,9 @@
     case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break;
     case native                 : tty->print("native"                 ); break;
     case native_synchronized    : tty->print("native_synchronized"    ); break;
+#ifdef GRAAL
+    case execute_compiled_method: tty->print("execute_compiled_method"); break;
+#endif
     case empty                  : tty->print("empty"                  ); break;
     case accessor               : tty->print("accessor"               ); break;
     case abstract               : tty->print("abstract"               ); break;
--- a/src/share/vm/interpreter/interpreter.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -48,12 +48,12 @@
   int         _size;                             // the size in bytes
   const char* _description;                      // a description of the codelet, for debugging & printing
   Bytecodes::Code _bytecode;                     // associated bytecode if any
-  DEBUG_ONLY(CodeComments _comments;)            // Comments for annotating assembler output.
+  DEBUG_ONLY(CodeStrings _strings;)              // Comments for annotating assembler output.
 
  public:
   // Initialization/finalization
   void    initialize(int size,
-                     CodeComments& comments)     { _size = size; DEBUG_ONLY(_comments.assign(comments);) }
+                     CodeStrings& strings)       { _size = size; DEBUG_ONLY(_strings.assign(strings);) }
   void    finalize()                             { ShouldNotCallThis(); }
 
   // General info/converters
@@ -131,7 +131,7 @@
 
 
     // commit Codelet
-    AbstractInterpreter::code()->commit((*_masm)->code()->pure_insts_size(), (*_masm)->code()->comments());
+    AbstractInterpreter::code()->commit((*_masm)->code()->pure_insts_size(), (*_masm)->code()->strings());
     // make sure nobody can use _masm outside a CodeletMark lifespan
     *_masm = NULL;
   }
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -568,11 +568,6 @@
 // be shared by method invocation and synchronized blocks.
 //%note synchronization_3
 
-static void trace_locking(Handle& h_locking_obj, bool is_locking) {
-  ObjectSynchronizer::trace_locking(h_locking_obj, false, true, is_locking);
-}
-
-
 //%note monitor_1
 IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
 #ifdef ASSERT
--- a/src/share/vm/interpreter/linkResolver.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/linkResolver.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -217,6 +217,7 @@
                                              TRAPS) {
   vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
   if (TraceMethodHandles) {
+    ResourceMark rm(THREAD);
     tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s",
                   vmIntrinsics::name_at(iid), klass->external_name(),
                   name->as_C_string(), full_signature->as_C_string());
@@ -231,6 +232,7 @@
       TempNewSymbol basic_signature =
         MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
       if (TraceMethodHandles) {
+        ResourceMark rm(THREAD);
         tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
                       name->as_C_string(),
                       full_signature->as_C_string(),
@@ -283,6 +285,8 @@
       }
       if (result.not_null()) {
 #ifdef ASSERT
+        ResourceMark rm(THREAD);
+
         TempNewSymbol basic_signature =
           MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
         int actual_size_of_params = result->size_of_parameters();
@@ -458,25 +462,27 @@
     Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
     {
       ResourceMark rm(THREAD);
-      char* failed_type_name =
+      Symbol* failed_type_symbol =
         SystemDictionary::check_signature_loaders(method_signature, loader,
                                                   class_loader, true, CHECK);
-      if (failed_type_name != NULL) {
+      if (failed_type_symbol != NULL) {
         const char* msg = "loader constraint violation: when resolving method"
           " \"%s\" the class loader (instance of %s) of the current class, %s,"
-          " and the class loader (instance of %s) for resolved class, %s, have"
+          " and the class loader (instance of %s) for the method's defining class, %s, have"
           " different Class objects for the type %s used in the signature";
         char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
         const char* loader1 = SystemDictionary::loader_name(loader());
         char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(class_loader());
-        char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string();
+        char* target = InstanceKlass::cast(resolved_method->method_holder())
+                       ->name()->as_C_string();
+        char* failed_type_name = failed_type_symbol->as_C_string();
         size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
-          strlen(current) + strlen(loader2) + strlen(resolved) +
-          strlen(failed_type_name);
+          strlen(current) + strlen(loader2) + strlen(target) +
+          strlen(failed_type_name) + 1;
         char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
         jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
-                     resolved, failed_type_name);
+                     target, failed_type_name);
         THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
       }
     }
@@ -520,26 +526,28 @@
     Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
     {
       ResourceMark rm(THREAD);
-      char* failed_type_name =
+      Symbol* failed_type_symbol =
         SystemDictionary::check_signature_loaders(method_signature, loader,
                                                   class_loader, true, CHECK);
-      if (failed_type_name != NULL) {
+      if (failed_type_symbol != NULL) {
         const char* msg = "loader constraint violation: when resolving "
           "interface method \"%s\" the class loader (instance of %s) of the "
           "current class, %s, and the class loader (instance of %s) for "
-          "resolved class, %s, have different Class objects for the type %s "
+          "the method's defining class, %s, have different Class objects for the type %s "
           "used in the signature";
         char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
         const char* loader1 = SystemDictionary::loader_name(loader());
         char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(class_loader());
-        char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string();
+        char* target = InstanceKlass::cast(resolved_method->method_holder())
+                       ->name()->as_C_string();
+        char* failed_type_name = failed_type_symbol->as_C_string();
         size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
-          strlen(current) + strlen(loader2) + strlen(resolved) +
-          strlen(failed_type_name);
+          strlen(current) + strlen(loader2) + strlen(target) +
+          strlen(failed_type_name) + 1;
         char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
         jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
-                     resolved, failed_type_name);
+                     target, failed_type_name);
         THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
       }
     }
@@ -642,12 +650,12 @@
     Symbol*  signature_ref  = pool->signature_ref_at(index);
     {
       ResourceMark rm(THREAD);
-      char* failed_type_name =
+      Symbol* failed_type_symbol =
         SystemDictionary::check_signature_loaders(signature_ref,
                                                   ref_loader, sel_loader,
                                                   false,
                                                   CHECK);
-      if (failed_type_name != NULL) {
+      if (failed_type_symbol != NULL) {
         const char* msg = "loader constraint violation: when resolving field"
           " \"%s\" the class loader (instance of %s) of the referring class, "
           "%s, and the class loader (instance of %s) for the field's resolved "
@@ -656,8 +664,9 @@
         const char* loader1 = SystemDictionary::loader_name(ref_loader());
         char* sel = InstanceKlass::cast(sel_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(sel_loader());
+        char* failed_type_name = failed_type_symbol->as_C_string();
         size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
-          strlen(sel) + strlen(loader2) + strlen(failed_type_name);
+          strlen(sel) + strlen(loader2) + strlen(failed_type_name) + 1;
         char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
         jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
                      failed_type_name);
@@ -803,7 +812,7 @@
     if (!direct_calling_default_method &&
         check_access &&
         // a) check if ACC_SUPER flag is set for the current class
-        current_klass->is_super() &&
+        (current_klass->is_super() || !AllowNonVirtualCalls) &&
         // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
         current_klass->is_subtype_of(method_klass()) &&
         current_klass() != method_klass() &&
@@ -1217,8 +1226,10 @@
   Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
-  if (TraceMethodHandles)
+  if (TraceMethodHandles) {
+    ResourceMark rm(THREAD);
     tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
+  }
   resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
 }
 
--- a/src/share/vm/interpreter/rewriter.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/rewriter.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -84,15 +84,13 @@
   const int length = _cp_cache_map.length();
   ClassLoaderData* loader_data = _pool->pool_holder()->class_loader_data();
   ConstantPoolCache* cache =
-      ConstantPoolCache::allocate(loader_data, length, CHECK);
+      ConstantPoolCache::allocate(loader_data, length, _cp_cache_map,
+                                  _invokedynamic_references_map, CHECK);
 
   // initialize object cache in constant pool
   _pool->initialize_resolved_references(loader_data, _resolved_references_map,
                                         _resolved_reference_limit,
                                         CHECK);
-
-  No_Safepoint_Verifier nsv;
-  cache->initialize(_cp_cache_map, _invokedynamic_references_map);
   _pool->set_cache(cache);
   cache->set_constant_pool(_pool());
 }
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -360,6 +360,9 @@
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
   method_entry(empty)
+#ifdef GRAAL
+  method_entry(execute_compiled_method)
+#endif
   method_entry(accessor)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
--- a/src/share/vm/memory/allocation.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/allocation.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -611,4 +611,23 @@
   void check()    PRODUCT_RETURN;
 };
 
+// Helper class to allocate arrays that may become large.
+// Uses the OS malloc for allocations smaller than ArrayAllocatorMallocLimit
+// and uses mapped memory for larger allocations.
+// Most OS mallocs do something similar but Solaris malloc does not revert
+// to mapped memory for large allocations. By default ArrayAllocatorMallocLimit
+// is set so that we always use malloc except for Solaris where we set the
+// limit to get mapped memory.
+template <class E, MEMFLAGS F>
+class ArrayAllocator : StackObj {
+  char* _addr;
+  bool _use_malloc;
+  size_t _size;
+ public:
+  ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { }
+  ~ArrayAllocator() { free(); }
+  E* allocate(size_t length);
+  void free();
+};
+
 #endif // SHARE_VM_MEMORY_ALLOCATION_HPP
--- a/src/share/vm/memory/allocation.inline.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/allocation.inline.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
 #define SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
 
+#include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 
 // Explicit C-heap memory management
@@ -107,5 +108,49 @@
    FreeHeap(p, F);
 }
 
+template <class E, MEMFLAGS F>
+E* ArrayAllocator<E, F>::allocate(size_t length) {
+  assert(_addr == NULL, "Already in use");
+
+  _size = sizeof(E) * length;
+  _use_malloc = _size < ArrayAllocatorMallocLimit;
+
+  if (_use_malloc) {
+    _addr = AllocateHeap(_size, F);
+    if (_addr == NULL && _size >=  (size_t)os::vm_allocation_granularity()) {
+      // malloc failed let's try with mmap instead
+      _use_malloc = false;
+    } else {
+      return (E*)_addr;
+    }
+  }
+
+  int alignment = os::vm_allocation_granularity();
+  _size = align_size_up(_size, alignment);
+
+  _addr = os::reserve_memory(_size, NULL, alignment);
+  if (_addr == NULL) {
+    vm_exit_out_of_memory(_size, "Allocator (reserve)");
+  }
+
+  bool success = os::commit_memory(_addr, _size, false /* executable */);
+  if (!success) {
+    vm_exit_out_of_memory(_size, "Allocator (commit)");
+  }
+
+  return (E*)_addr;
+}
+
+template<class E, MEMFLAGS F>
+void ArrayAllocator<E, F>::free() {
+  if (_addr != NULL) {
+    if (_use_malloc) {
+      FreeHeap(_addr, F);
+    } else {
+      os::release_memory(_addr, _size);
+    }
+    _addr = NULL;
+  }
+}
 
 #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
--- a/src/share/vm/memory/cardTableModRefBS.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/cardTableModRefBS.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -694,7 +694,7 @@
     if (failed) {
       if (!failures) {
         tty->cr();
-        tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]");
+        tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]", start, end);
         tty->print_cr("==   %sexpecting value: %d",
                       (val_equals) ? "" : "not ", val);
         failures = true;
--- a/src/share/vm/memory/cardTableRS.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/cardTableRS.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -353,7 +353,7 @@
     assert(jp >= _begin && jp < _end,
            err_msg("Error: jp " PTR_FORMAT " should be within "
                    "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")",
-                   _begin, _end));
+                   jp, _begin, _end));
     oop obj = oopDesc::load_decode_heap_oop(p);
     guarantee(obj == NULL || (HeapWord*)obj >= _boundary,
               err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
--- a/src/share/vm/memory/collectorPolicy.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/collectorPolicy.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -532,7 +532,7 @@
 
   // Loop until the allocation is satisified,
   // or unsatisfied after GC.
-  for (int try_count = 1; /* return or throw */; try_count += 1) {
+  for (int try_count = 1, gclocker_stalled_count = 0; /* return or throw */; try_count += 1) {
     HandleMark hm; // discard any handles allocated in each iteration
 
     // First allocation attempt is lock-free.
@@ -576,6 +576,10 @@
           }
         }
 
+        if (gclocker_stalled_count > GCLockerRetryAllocationCount) {
+          return NULL; // we didn't get to do a GC and we didn't get any memory
+        }
+
         // If this thread is not in a jni critical section, we stall
         // the requestor until the critical section has cleared and
         // GC allowed. When the critical section clears, a GC is
@@ -587,6 +591,7 @@
           MutexUnlocker mul(Heap_lock);
           // Wait for JNI critical section to be exited
           GC_locker::stall_until_clear();
+          gclocker_stalled_count += 1;
           continue;
         } else {
           if (CheckJNICalls) {
@@ -620,7 +625,7 @@
 
       const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
       const bool softrefs_clear = all_soft_refs_clear();
-      assert(!limit_exceeded || softrefs_clear, "Should have been cleared");
+
       if (limit_exceeded && softrefs_clear) {
         *gc_overhead_limit_was_exceeded = true;
         size_policy()->set_gc_overhead_limit_exceeded(false);
--- a/src/share/vm/memory/filemap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/filemap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -372,7 +372,7 @@
   // other reserved memory (like the code cache).
   ReservedSpace rs(size, alignment, false, requested_addr);
   if (!rs.is_reserved()) {
-    fail_continue(err_msg("Unable to reserved shared space at required address " INTPTR_FORMAT, requested_addr));
+    fail_continue(err_msg("Unable to reserve shared space at required address " INTPTR_FORMAT, requested_addr));
     return rs;
   }
   // the reserved virtual memory is for mapping class data sharing archive
--- a/src/share/vm/memory/filemap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/filemap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -112,12 +112,19 @@
   char*  region_base(int i)           { return _header._space[i]._base; }
   struct FileMapHeader* header()      { return &_header; }
 
-  static void set_current_info(FileMapInfo* info)  { _current_info = info; }
-  static FileMapInfo* current_info()  { return _current_info; }
+  static void set_current_info(FileMapInfo* info) {
+    CDS_ONLY(_current_info = info;)
+  }
+
+  static FileMapInfo* current_info() {
+    CDS_ONLY(return _current_info;)
+    NOT_CDS(return NULL;)
+  }
+
   static void assert_mark(bool check);
 
   // File manipulation.
-  bool  initialize();
+  bool  initialize() NOT_CDS_RETURN_(false);
   bool  open_for_read();
   void  open_for_write();
   void  write_header();
@@ -141,7 +148,7 @@
   void fail_continue(const char *msg, ...);
 
   // Return true if given address is in the mapped shared space.
-  bool is_in_shared_space(const void* p);
+  bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
 };
 
 #endif // SHARE_VM_MEMORY_FILEMAP_HPP
--- a/src/share/vm/memory/genCollectedHeap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -554,6 +554,8 @@
     }
 
     if (complete) {
+      // Delete metaspaces for unloaded class loaders and clean up loader_data graph
+      ClassLoaderDataGraph::purge();
       // Resize the metaspace capacity after full collections
       MetaspaceGC::compute_new_size();
       update_full_collections_completed();
@@ -564,11 +566,6 @@
 
     gc_epilogue(complete);
 
-    // Delete metaspaces for unloaded class loaders and clean up loader_data graph
-    if (complete) {
-      ClassLoaderDataGraph::purge();
-    }
-
     if (must_restore_marks_for_biased_locking) {
       BiasedLocking::restore_marks();
     }
@@ -822,12 +819,13 @@
 // Returns "TRUE" iff "p" points into the committed areas of the heap.
 bool GenCollectedHeap::is_in(const void* p) const {
   #ifndef ASSERT
-  guarantee(VerifyBeforeGC   ||
-            VerifyDuringGC   ||
-            VerifyBeforeExit ||
-            PrintAssembly    ||
-            tty->count() != 0 ||   // already printing
-            VerifyAfterGC    ||
+  guarantee(VerifyBeforeGC      ||
+            VerifyDuringGC      ||
+            VerifyBeforeExit    ||
+            VerifyDuringStartup ||
+            PrintAssembly       ||
+            tty->count() != 0   ||   // already printing
+            VerifyAfterGC       ||
     VMError::fatal_error_in_progress(), "too expensive");
 
   #endif
@@ -1135,6 +1133,17 @@
 #endif // INCLUDE_ALL_GCS
 }
 
+void GenCollectedHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    st->cr();
+    CMSCollector::print_on_error(st);
+  }
+#endif // INCLUDE_ALL_GCS
+}
+
 void GenCollectedHeap::print_tracing_info() const {
   if (TraceGen0Time) {
     get_gen(0)->print_summary_info();
--- a/src/share/vm/memory/genCollectedHeap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/genCollectedHeap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -344,6 +344,7 @@
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
   virtual void print_tracing_info() const;
+  virtual void print_on_error(outputStream* st) const;
 
   // PrintGC, PrintGCDetails support
   void print_heap_change(size_t prev_used) const;
--- a/src/share/vm/memory/generation.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/generation.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -382,7 +382,9 @@
 CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
                                int level,
                                GenRemSet* remset) :
-  Generation(rs, initial_byte_size, level), _rs(remset)
+  Generation(rs, initial_byte_size, level), _rs(remset),
+  _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
+  _used_at_prologue()
 {
   HeapWord* start = (HeapWord*)rs.base();
   size_t reserved_byte_size = rs.size();
@@ -406,6 +408,9 @@
     // the end if we try.
     guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
   }
+  _min_heap_delta_bytes = MinHeapDeltaBytes;
+  _capacity_at_prologue = initial_byte_size;
+  _used_at_prologue = 0;
 }
 
 bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
@@ -457,6 +462,160 @@
 }
 
 
+void CardGeneration::compute_new_size() {
+  assert(_shrink_factor <= 100, "invalid shrink factor");
+  size_t current_shrink_factor = _shrink_factor;
+  _shrink_factor = 0;
+
+  // We don't have floating point command-line arguments
+  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
+  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
+  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
+
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  const double min_tmp = used_after_gc / maximum_used_percentage;
+  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
+  // Don't shrink less than the initial generation size
+  minimum_desired_capacity = MAX2(minimum_desired_capacity,
+                                  spec()->init_size());
+  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
+
+  if (PrintGC && Verbose) {
+    const size_t free_after_gc = free();
+    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
+    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
+    gclog_or_tty->print_cr("  "
+                  "  minimum_free_percentage: %6.2f"
+                  "  maximum_used_percentage: %6.2f",
+                  minimum_free_percentage,
+                  maximum_used_percentage);
+    gclog_or_tty->print_cr("  "
+                  "   free_after_gc   : %6.1fK"
+                  "   used_after_gc   : %6.1fK"
+                  "   capacity_after_gc   : %6.1fK",
+                  free_after_gc / (double) K,
+                  used_after_gc / (double) K,
+                  capacity_after_gc / (double) K);
+    gclog_or_tty->print_cr("  "
+                  "   free_percentage: %6.2f",
+                  free_percentage);
+  }
+
+  if (capacity_after_gc < minimum_desired_capacity) {
+    // If we have less free space than we want then expand
+    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
+    // Don't expand unless it's significant
+    if (expand_bytes >= _min_heap_delta_bytes) {
+      expand(expand_bytes, 0); // safe if expansion fails
+    }
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("    expanding:"
+                    "  minimum_desired_capacity: %6.1fK"
+                    "  expand_bytes: %6.1fK"
+                    "  _min_heap_delta_bytes: %6.1fK",
+                    minimum_desired_capacity / (double) K,
+                    expand_bytes / (double) K,
+                    _min_heap_delta_bytes / (double) K);
+    }
+    return;
+  }
+
+  // No expansion, now see if we want to shrink
+  size_t shrink_bytes = 0;
+  // We would never want to shrink more than this
+  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
+
+  if (MaxHeapFreeRatio < 100) {
+    const double maximum_free_percentage = MaxHeapFreeRatio / 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));
+    maximum_desired_capacity = MAX2(maximum_desired_capacity,
+                                    spec()->init_size());
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  maximum_free_percentage: %6.2f"
+                             "  minimum_used_percentage: %6.2f",
+                             maximum_free_percentage,
+                             minimum_used_percentage);
+      gclog_or_tty->print_cr("  "
+                             "  _capacity_at_prologue: %6.1fK"
+                             "  minimum_desired_capacity: %6.1fK"
+                             "  maximum_desired_capacity: %6.1fK",
+                             _capacity_at_prologue / (double) K,
+                             minimum_desired_capacity / (double) K,
+                             maximum_desired_capacity / (double) K);
+    }
+    assert(minimum_desired_capacity <= maximum_desired_capacity,
+           "sanity check");
+
+    if (capacity_after_gc > maximum_desired_capacity) {
+      // Capacity too large, compute shrinking size
+      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
+      // We don't want shrink all the way back to initSize if people call
+      // System.gc(), because some programs do that between "phases" and then
+      // we'd just have to grow the heap up again for the next phase.  So we
+      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
+      // on the third call, and 100% by the fourth call.  But if we recompute
+      // size without shrinking, it goes back to 0%.
+      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+      if (current_shrink_factor == 0) {
+        _shrink_factor = 10;
+      } else {
+        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
+      }
+      if (PrintGC && Verbose) {
+        gclog_or_tty->print_cr("  "
+                      "  shrinking:"
+                      "  initSize: %.1fK"
+                      "  maximum_desired_capacity: %.1fK",
+                      spec()->init_size() / (double) K,
+                      maximum_desired_capacity / (double) K);
+        gclog_or_tty->print_cr("  "
+                      "  shrink_bytes: %.1fK"
+                      "  current_shrink_factor: %d"
+                      "  new shrink factor: %d"
+                      "  _min_heap_delta_bytes: %.1fK",
+                      shrink_bytes / (double) K,
+                      current_shrink_factor,
+                      _shrink_factor,
+                      _min_heap_delta_bytes / (double) K);
+      }
+    }
+  }
+
+  if (capacity_after_gc > _capacity_at_prologue) {
+    // We might have expanded for promotions, in which case we might want to
+    // take back that expansion if there's room after GC.  That keeps us from
+    // stretching the heap with promotions when there's plenty of room.
+    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
+    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
+    // We have two shrinking computations, take the largest
+    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
+    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  aggressive shrinking:"
+                             "  _capacity_at_prologue: %.1fK"
+                             "  capacity_after_gc: %.1fK"
+                             "  expansion_for_promotion: %.1fK"
+                             "  shrink_bytes: %.1fK",
+                             capacity_after_gc / (double) K,
+                             _capacity_at_prologue / (double) K,
+                             expansion_for_promotion / (double) K,
+                             shrink_bytes / (double) K);
+    }
+  }
+  // Don't shrink unless it's significant
+  if (shrink_bytes >= _min_heap_delta_bytes) {
+    shrink(shrink_bytes);
+  }
+}
+
 // Currently nothing to do.
 void CardGeneration::prepare_for_verify() {}
 
--- a/src/share/vm/memory/generation.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/generation.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -634,6 +634,17 @@
   // This is local to this generation.
   BlockOffsetSharedArray* _bts;
 
+  // current shrinking effect: this damps shrinking when the heap gets empty.
+  size_t _shrink_factor;
+
+  size_t _min_heap_delta_bytes;   // Minimum amount to expand.
+
+  // Some statistics from before gc started.
+  // These are gathered in the gc_prologue (and should_collect)
+  // to control growing/shrinking policy in spite of promotions.
+  size_t _capacity_at_prologue;
+  size_t _used_at_prologue;
+
   CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
                  GenRemSet* remset);
 
@@ -644,6 +655,11 @@
   // necessarily the full "bytes") was done.
   virtual bool expand(size_t bytes, size_t expand_bytes);
 
+  // Shrink generation with specified size (returns false if unable to shrink)
+  virtual void shrink(size_t bytes) = 0;
+
+  virtual void compute_new_size();
+
   virtual void clear_remembered_set();
 
   virtual void invalidate_remembered_set();
@@ -667,7 +683,6 @@
   friend class VM_PopulateDumpSharedSpace;
 
  protected:
-  size_t     _min_heap_delta_bytes;   // Minimum amount to expand.
   ContiguousSpace*  _the_space;       // actual space holding objects
   WaterMark  _last_gc;                // watermark between objects allocated before
                                       // and after last GC.
@@ -688,11 +703,10 @@
 
  public:
   OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size,
-                               size_t min_heap_delta_bytes,
                                int level, GenRemSet* remset,
                                ContiguousSpace* space) :
     CardGeneration(rs, initial_byte_size, level, remset),
-    _the_space(space), _min_heap_delta_bytes(min_heap_delta_bytes)
+    _the_space(space)
   {}
 
   inline bool is_in(const void* p) const;
--- a/src/share/vm/memory/heap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/heap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -79,13 +79,6 @@
 }
 
 
-static size_t align_to_allocation_size(size_t size) {
-  const size_t alignment = (size_t)os::vm_allocation_granularity();
-  assert(is_power_of_2(alignment), "no kidding ???");
-  return (size + alignment - 1) & ~(alignment - 1);
-}
-
-
 void CodeHeap::on_code_mapping(char* base, size_t size) {
 #ifdef LINUX
   extern void linux_wrap_code(char* base, size_t size);
--- a/src/share/vm/memory/metablock.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/metablock.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
--- a/src/share/vm/memory/metaspace.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/metaspace.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -52,7 +52,6 @@
 const uint metadata_deallocate_a_lot_block = 10;
 const uint metadata_deallocate_a_lock_chunk = 3;
 size_t const allocation_from_dictionary_limit = 64 * K;
-const size_t metadata_deallocate = 0xf5f5f5f5;
 
 MetaWord* last_allocated = 0;
 
@@ -335,27 +334,19 @@
 
   // byte_size is the size of the associated virtualspace.
 VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), _rs(0) {
-  // This allocates memory with mmap.  For DumpSharedspaces, allocate the
-  // space at low memory so that other shared images don't conflict.
-  // This is the same address as memory needed for UseCompressedOops but
-  // compressed oops don't work with CDS (offsets in metadata are wrong), so
-  // borrow the same address.
+  // align up to vm allocation granularity
+  byte_size = align_size_up(byte_size, os::vm_allocation_granularity());
+
+  // This allocates memory with mmap.  For DumpSharedspaces, try to reserve
+  // configurable address, generally at the top of the Java heap so other
+  // memory addresses don't conflict.
   if (DumpSharedSpaces) {
-    char* shared_base = (char*)HeapBaseMinAddress;
+    char* shared_base = (char*)SharedBaseAddress;
     _rs = ReservedSpace(byte_size, 0, false, shared_base, 0);
     if (_rs.is_reserved()) {
-      assert(_rs.base() == shared_base, "should match");
+      assert(shared_base == 0 || _rs.base() == shared_base, "should match");
     } else {
-      // If we are dumping the heap, then allocate a wasted block of address
-      // space in order to push the heap to a lower address.  This extra
-      // address range allows for other (or larger) libraries to be loaded
-      // without them occupying the space required for the shared spaces.
-      uintx reserved = 0;
-      uintx block_size = 64*1024*1024;
-      while (reserved < SharedDummyBlockSize) {
-        char* dummy = os::reserve_memory(block_size);
-        reserved += block_size;
-      }
+      // Get a mmap region anywhere if the SharedBaseAddress fails.
       _rs = ReservedSpace(byte_size);
     }
     MetaspaceShared::set_shared_rs(&_rs);
@@ -1101,25 +1092,24 @@
 }
 
 bool MetaspaceGC::should_expand(VirtualSpaceList* vsl, size_t word_size) {
+  // If the user wants a limit, impose one.
+  if (!FLAG_IS_DEFAULT(MaxMetaspaceSize) &&
+      MetaspaceAux::reserved_in_bytes() >= MaxMetaspaceSize) {
+    return false;
+  }
 
   // Class virtual space should always be expanded.  Call GC for the other
   // metadata virtual space.
   if (vsl == Metaspace::class_space_list()) return true;
 
-  // If the user wants a limit, impose one.
-  size_t max_metaspace_size_words = MaxMetaspaceSize / BytesPerWord;
-  size_t metaspace_size_words = MetaspaceSize / BytesPerWord;
-  if (!FLAG_IS_DEFAULT(MaxMetaspaceSize) &&
-      vsl->capacity_words_sum() >= max_metaspace_size_words) {
-    return false;
-  }
-
   // If this is part of an allocation after a GC, expand
   // unconditionally.
   if(MetaspaceGC::expand_after_GC()) {
     return true;
   }
 
+  size_t metaspace_size_words = MetaspaceSize / BytesPerWord;
+
   // If the capacity is below the minimum capacity, allow the
   // expansion.  Also set the high-water-mark (capacity_until_GC)
   // to that minimum capacity so that a GC will not be induced
@@ -1309,8 +1299,7 @@
       gclog_or_tty->print_cr("  metaspace HWM: %.1fK", new_capacity_until_GC / (double) K);
     }
   }
-  assert(vsl->used_bytes_sum() == used_after_gc &&
-         used_after_gc <= vsl->capacity_bytes_sum(),
+  assert(used_after_gc <= vsl->capacity_bytes_sum(),
          "sanity check");
 
 }
@@ -1970,6 +1959,9 @@
 }
 
 SpaceManager::~SpaceManager() {
+  // This call this->_lock which can't be done while holding expand_lock()
+  const size_t in_use_before = sum_capacity_in_chunks_in_use();
+
   MutexLockerEx fcl(SpaceManager::expand_lock(),
                     Mutex::_no_safepoint_check_flag);
 
@@ -1987,7 +1979,7 @@
 
   // Have to update before the chunks_in_use lists are emptied
   // below.
-  chunk_manager->inc_free_chunks_total(sum_capacity_in_chunks_in_use(),
+  chunk_manager->inc_free_chunks_total(in_use_before,
                                        sum_count_in_chunks_in_use());
 
   // Add all the chunks in use by this space manager
@@ -2440,7 +2432,8 @@
              free_chunks_capacity_bytes / K,
              used_and_free / K,
              capacity_bytes / K);
-  assert(used_and_free == capacity_bytes, "Accounting is wrong");
+  // Accounting can only be correct if we got the values during a safepoint
+  assert(!SafepointSynchronize::is_at_safepoint() || used_and_free == capacity_bytes, "Accounting is wrong");
 }
 
 // Print total fragmentation for class and data metaspaces separately
--- a/src/share/vm/memory/metaspaceCounters.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/metaspaceCounters.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -25,12 +25,14 @@
 #include "precompiled.hpp"
 #include "memory/metaspaceCounters.hpp"
 #include "memory/resourceArea.hpp"
-
-#define METASPACE_NAME "perm"
+#include "utilities/exceptions.hpp"
 
 MetaspaceCounters* MetaspaceCounters::_metaspace_counters = NULL;
 
-MetaspaceCounters::MetaspaceCounters() {
+MetaspaceCounters::MetaspaceCounters() :
+    _capacity(NULL),
+    _used(NULL),
+    _max_capacity(NULL) {
   if (UsePerfData) {
     size_t min_capacity = MetaspaceAux::min_chunk_size();
     size_t max_capacity = MetaspaceAux::reserved_in_bytes();
@@ -41,6 +43,25 @@
   }
 }
 
+static PerfVariable* create_ms_variable(const char *ns,
+                                        const char *name,
+                                        size_t value,
+                                        TRAPS) {
+  const char *path = PerfDataManager::counter_name(ns, name);
+  PerfVariable *result =
+      PerfDataManager::create_variable(SUN_GC, path, PerfData::U_Bytes, value,
+                                       CHECK_NULL);
+  return result;
+}
+
+static void create_ms_constant(const char *ns,
+                               const char *name,
+                               size_t value,
+                               TRAPS) {
+  const char *path = PerfDataManager::counter_name(ns, name);
+  PerfDataManager::create_constant(SUN_GC, path, PerfData::U_Bytes, value, CHECK);
+}
+
 void MetaspaceCounters::initialize(size_t min_capacity,
                                    size_t max_capacity,
                                    size_t curr_capacity,
@@ -50,93 +71,32 @@
     EXCEPTION_MARK;
     ResourceMark rm;
 
-    // Create a name that will be recognized by jstat tools as
-    // the perm gen.  Change this to a Metaspace name when the
-    // tools are fixed.
-    // name to recognize "sun.gc.generation.2.*"
-
-    const char* name = METASPACE_NAME;
-    const int ordinal = 2;
-    const int spaces = 1;
-
-    const char* cns = PerfDataManager::name_space("generation", ordinal);
-
-    _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtClass);
-    strcpy(_name_space, cns);
-
-    const char* cname = PerfDataManager::counter_name(_name_space, "name");
-    PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
-
-    // End of perm gen like name creation
-
-    cname = PerfDataManager::counter_name(_name_space, "spaces");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None,
-                                     spaces, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "minCapacity");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
-                                     min_capacity, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "maxCapacity");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
-                                     max_capacity, CHECK);
+    const char *ms = "metaspace";
 
-    cname = PerfDataManager::counter_name(_name_space, "capacity");
-    _current_size =
-      PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
-                                       curr_capacity, CHECK);
-
-    // SpaceCounter like counters
-    // name to recognize "sun.gc.generation.2.space.0.*"
-    {
-      const int space_ordinal = 0;
-      const char* cns = PerfDataManager::name_space(_name_space, "space",
-                                                    space_ordinal);
-
-      char* space_name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtClass);
-      strcpy(space_name_space, cns);
-
-      const char* cname = PerfDataManager::counter_name(space_name_space, "name");
-      PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
-
-      cname = PerfDataManager::counter_name(space_name_space, "maxCapacity");
-      _max_capacity = PerfDataManager::create_variable(SUN_GC, cname,
-                                                       PerfData::U_Bytes,
-                                                       (jlong)max_capacity, CHECK);
-
-      cname = PerfDataManager::counter_name(space_name_space, "capacity");
-      _capacity = PerfDataManager::create_variable(SUN_GC, cname,
-                                                   PerfData::U_Bytes,
-                                                   curr_capacity, CHECK);
-
-      cname = PerfDataManager::counter_name(space_name_space, "used");
-      _used = PerfDataManager::create_variable(SUN_GC,
-                                               cname,
-                                               PerfData::U_Bytes,
-                                               used,
-                                               CHECK);
-
-    cname = PerfDataManager::counter_name(space_name_space, "initCapacity");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
-                                     min_capacity, CHECK);
-    }
+    create_ms_constant(ms, "minCapacity", min_capacity, CHECK);
+    _max_capacity = create_ms_variable(ms, "maxCapacity", max_capacity, CHECK);
+    _capacity = create_ms_variable(ms, "capacity", curr_capacity, CHECK);
+    _used = create_ms_variable(ms, "used", used, CHECK);
   }
 }
 
 void MetaspaceCounters::update_capacity() {
   assert(UsePerfData, "Should not be called unless being used");
+  assert(_capacity != NULL, "Should be initialized");
   size_t capacity_in_bytes = MetaspaceAux::capacity_in_bytes();
   _capacity->set_value(capacity_in_bytes);
 }
 
 void MetaspaceCounters::update_used() {
   assert(UsePerfData, "Should not be called unless being used");
+  assert(_used != NULL, "Should be initialized");
   size_t used_in_bytes = MetaspaceAux::used_in_bytes();
   _used->set_value(used_in_bytes);
 }
 
 void MetaspaceCounters::update_max_capacity() {
   assert(UsePerfData, "Should not be called unless being used");
+  assert(_max_capacity != NULL, "Should be initialized");
   size_t reserved_in_bytes = MetaspaceAux::reserved_in_bytes();
   _max_capacity->set_value(reserved_in_bytes);
 }
@@ -146,18 +106,19 @@
     update_used();
     update_capacity();
     update_max_capacity();
-    _current_size->set_value(MetaspaceAux::reserved_in_bytes());
   }
 }
 
 void MetaspaceCounters::initialize_performance_counters() {
   if (UsePerfData) {
+    assert(_metaspace_counters == NULL, "Should only be initialized once");
     _metaspace_counters = new MetaspaceCounters();
   }
 }
 
 void MetaspaceCounters::update_performance_counters() {
   if (UsePerfData) {
+    assert(_metaspace_counters != NULL, "Should be initialized");
     _metaspace_counters->update_all();
   }
 }
--- a/src/share/vm/memory/metaspaceCounters.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/metaspaceCounters.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -29,11 +29,9 @@
 
 class MetaspaceCounters: public CHeapObj<mtClass> {
   friend class VMStructs;
-  PerfVariable*      _current_size;
   PerfVariable*      _capacity;
   PerfVariable*      _used;
   PerfVariable*      _max_capacity;
-  char*              _name_space;
   static MetaspaceCounters* _metaspace_counters;
   void initialize(size_t min_capacity,
                   size_t max_capacity,
--- a/src/share/vm/memory/sharedHeap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/sharedHeap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -178,7 +178,7 @@
       SystemDictionary::always_strong_oops_do(roots);
       ClassLoaderDataGraph::always_strong_oops_do(roots, klass_closure, !is_scavenging);
     } else {
-      ShouldNotReachHere2("We should always have selected either SO_AllClasses or SO_SystemClasses");
+      fatal("We should always have selected either SO_AllClasses or SO_SystemClasses");
     }
   }
 
--- a/src/share/vm/memory/tenuredGeneration.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -39,7 +39,7 @@
                                      size_t initial_byte_size, int level,
                                      GenRemSet* remset) :
   OneContigSpaceCardGeneration(rs, initial_byte_size,
-                               MinHeapDeltaBytes, level, remset, NULL)
+                               level, remset, NULL)
 {
   HeapWord* bottom = (HeapWord*) _virtual_space.low();
   HeapWord* end    = (HeapWord*) _virtual_space.high();
@@ -86,162 +86,6 @@
   return "tenured generation";
 }
 
-void TenuredGeneration::compute_new_size() {
-  assert(_shrink_factor <= 100, "invalid shrink factor");
-  size_t current_shrink_factor = _shrink_factor;
-  _shrink_factor = 0;
-
-  // We don't have floating point command-line arguments
-  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
-  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
-  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
-
-  // Compute some numbers about the state of the heap.
-  const size_t used_after_gc = used();
-  const size_t capacity_after_gc = capacity();
-
-  const double min_tmp = used_after_gc / maximum_used_percentage;
-  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
-  // Don't shrink less than the initial generation size
-  minimum_desired_capacity = MAX2(minimum_desired_capacity,
-                                  spec()->init_size());
-  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
-
-  if (PrintGC && Verbose) {
-    const size_t free_after_gc = free();
-    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
-    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
-    gclog_or_tty->print_cr("  "
-                  "  minimum_free_percentage: %6.2f"
-                  "  maximum_used_percentage: %6.2f",
-                  minimum_free_percentage,
-                  maximum_used_percentage);
-    gclog_or_tty->print_cr("  "
-                  "   free_after_gc   : %6.1fK"
-                  "   used_after_gc   : %6.1fK"
-                  "   capacity_after_gc   : %6.1fK",
-                  free_after_gc / (double) K,
-                  used_after_gc / (double) K,
-                  capacity_after_gc / (double) K);
-    gclog_or_tty->print_cr("  "
-                  "   free_percentage: %6.2f",
-                  free_percentage);
-  }
-
-  if (capacity_after_gc < minimum_desired_capacity) {
-    // If we have less free space than we want then expand
-    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
-    // Don't expand unless it's significant
-    if (expand_bytes >= _min_heap_delta_bytes) {
-      expand(expand_bytes, 0); // safe if expansion fails
-    }
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("    expanding:"
-                    "  minimum_desired_capacity: %6.1fK"
-                    "  expand_bytes: %6.1fK"
-                    "  _min_heap_delta_bytes: %6.1fK",
-                    minimum_desired_capacity / (double) K,
-                    expand_bytes / (double) K,
-                    _min_heap_delta_bytes / (double) K);
-    }
-    return;
-  }
-
-  // No expansion, now see if we want to shrink
-  size_t shrink_bytes = 0;
-  // We would never want to shrink more than this
-  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
-
-  if (MaxHeapFreeRatio < 100) {
-    const double maximum_free_percentage = MaxHeapFreeRatio / 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));
-    maximum_desired_capacity = MAX2(maximum_desired_capacity,
-                                    spec()->init_size());
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  maximum_free_percentage: %6.2f"
-                             "  minimum_used_percentage: %6.2f",
-                             maximum_free_percentage,
-                             minimum_used_percentage);
-      gclog_or_tty->print_cr("  "
-                             "  _capacity_at_prologue: %6.1fK"
-                             "  minimum_desired_capacity: %6.1fK"
-                             "  maximum_desired_capacity: %6.1fK",
-                             _capacity_at_prologue / (double) K,
-                             minimum_desired_capacity / (double) K,
-                             maximum_desired_capacity / (double) K);
-    }
-    assert(minimum_desired_capacity <= maximum_desired_capacity,
-           "sanity check");
-
-    if (capacity_after_gc > maximum_desired_capacity) {
-      // Capacity too large, compute shrinking size
-      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
-      // We don't want shrink all the way back to initSize if people call
-      // System.gc(), because some programs do that between "phases" and then
-      // we'd just have to grow the heap up again for the next phase.  So we
-      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
-      // on the third call, and 100% by the fourth call.  But if we recompute
-      // size without shrinking, it goes back to 0%.
-      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
-      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-      if (current_shrink_factor == 0) {
-        _shrink_factor = 10;
-      } else {
-        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
-      }
-      if (PrintGC && Verbose) {
-        gclog_or_tty->print_cr("  "
-                      "  shrinking:"
-                      "  initSize: %.1fK"
-                      "  maximum_desired_capacity: %.1fK",
-                      spec()->init_size() / (double) K,
-                      maximum_desired_capacity / (double) K);
-        gclog_or_tty->print_cr("  "
-                      "  shrink_bytes: %.1fK"
-                      "  current_shrink_factor: %d"
-                      "  new shrink factor: %d"
-                      "  _min_heap_delta_bytes: %.1fK",
-                      shrink_bytes / (double) K,
-                      current_shrink_factor,
-                      _shrink_factor,
-                      _min_heap_delta_bytes / (double) K);
-      }
-    }
-  }
-
-  if (capacity_after_gc > _capacity_at_prologue) {
-    // We might have expanded for promotions, in which case we might want to
-    // take back that expansion if there's room after GC.  That keeps us from
-    // stretching the heap with promotions when there's plenty of room.
-    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
-    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
-    // We have two shrinking computations, take the largest
-    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
-    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  aggressive shrinking:"
-                             "  _capacity_at_prologue: %.1fK"
-                             "  capacity_after_gc: %.1fK"
-                             "  expansion_for_promotion: %.1fK"
-                             "  shrink_bytes: %.1fK",
-                             capacity_after_gc / (double) K,
-                             _capacity_at_prologue / (double) K,
-                             expansion_for_promotion / (double) K,
-                             shrink_bytes / (double) K);
-    }
-  }
-  // Don't shrink unless it's significant
-  if (shrink_bytes >= _min_heap_delta_bytes) {
-    shrink(shrink_bytes);
-  }
-  assert(used() == used_after_gc && used_after_gc <= capacity(),
-         "sanity check");
-}
-
 void TenuredGeneration::gc_prologue(bool full) {
   _capacity_at_prologue = capacity();
   _used_at_prologue = used();
@@ -312,6 +156,19 @@
                                         size, is_tlab);
 }
 
+void TenuredGeneration::compute_new_size() {
+  assert_locked_or_safepoint(Heap_lock);
+
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  CardGeneration::compute_new_size();
+
+  assert(used() == used_after_gc && used_after_gc <= capacity(),
+         err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
+         " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()));
+}
 void TenuredGeneration::update_gc_stats(int current_level,
                                         bool full) {
   // If the next lower level(s) has been collected, gather any statistics
--- a/src/share/vm/memory/tenuredGeneration.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/tenuredGeneration.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -38,13 +38,6 @@
 class TenuredGeneration: public OneContigSpaceCardGeneration {
   friend class VMStructs;
  protected:
-  // current shrinking effect: this damps shrinking when the heap gets empty.
-  size_t _shrink_factor;
-  // Some statistics from before gc started.
-  // These are gathered in the gc_prologue (and should_collect)
-  // to control growing/shrinking policy in spite of promotions.
-  size_t _capacity_at_prologue;
-  size_t _used_at_prologue;
 
 #if INCLUDE_ALL_GCS
   // To support parallel promotion: an array of parallel allocation
@@ -80,9 +73,6 @@
     return !CollectGen0First;
   }
 
-  // Mark sweep support
-  void compute_new_size();
-
   virtual void gc_prologue(bool full);
   virtual void gc_epilogue(bool full);
   bool should_collect(bool   full,
@@ -93,6 +83,7 @@
                        bool clear_all_soft_refs,
                        size_t size,
                        bool is_tlab);
+  virtual void compute_new_size();
 
 #if INCLUDE_ALL_GCS
   // Overrides.
--- a/src/share/vm/memory/universe.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/memory/universe.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -885,6 +885,8 @@
   // the actual alignment depends on its size.
   Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment));
   size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment);
+  assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
+      "heap size is too big for compressed oops");
   char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
 
   ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr);
@@ -951,15 +953,6 @@
 void universe2_init() {
   EXCEPTION_MARK;
   Universe::genesis(CATCH);
-  // Although we'd like to verify here that the state of the heap
-  // is good, we can't because the main thread has not yet added
-  // itself to the threads list (so, using current interfaces
-  // we can't "fill" its TLAB), unless TLABs are disabled.
-  if (VerifyBeforeGC && !UseTLAB &&
-      Universe::heap()->total_collections() >= VerifyGCStartAt) {
-     Universe::heap()->prepare_for_verify();
-     Universe::verify();   // make sure we're starting with a clean slate
-  }
 }
 
 
@@ -1333,6 +1326,8 @@
 static uintptr_t _verify_klass_data[2] = {0, (uintptr_t)-1};
 
 
+#ifndef PRODUCT
+
 static void calculate_verify_data(uintptr_t verify_data[2],
                                   HeapWord* low_boundary,
                                   HeapWord* high_boundary) {
@@ -1367,9 +1362,7 @@
   verify_data[1] = bits;
 }
 
-
 // Oop verification (see MacroAssembler::verify_oop)
-#ifndef PRODUCT
 
 uintptr_t Universe::verify_oop_mask() {
   MemRegion m = heap()->reserved_region();
--- a/src/share/vm/oops/constMethod.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/constMethod.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -55,11 +55,24 @@
   set_stackmap_data(NULL);
   set_code_size(byte_code_size);
   set_constMethod_size(size);
-  set_inlined_tables_length(sizes);
+  set_inlined_tables_length(sizes); // sets _flags
   set_method_type(method_type);
   assert(this->size() == size, "wrong size for object");
+  set_name_index(0);
+  set_signature_index(0);
+  set_constants(NULL);
+  set_max_stack(0);
+  set_max_locals(0);
+  set_method_idnum(0);
+  set_size_of_parameters(0);
 }
 
+// Accessor that copies to metadata.
+void ConstMethod::copy_stackmap_data(ClassLoaderData* loader_data,
+                                     u1* sd, int length, TRAPS) {
+  _stackmap_data = MetadataFactory::new_array<u1>(loader_data, length, CHECK);
+  memcpy((void*)_stackmap_data->adr_at(0), (void*)sd, length);
+}
 
 // Deallocate metadata fields associated with ConstMethod*
 void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
@@ -350,6 +363,26 @@
   return (AnnotationArray**)constMethod_end() - offset;
 }
 
+// copy annotations from 'cm' to 'this'
+void ConstMethod::copy_annotations_from(ConstMethod* cm) {
+  if (cm->has_method_annotations()) {
+    assert(has_method_annotations(), "should be allocated already");
+    set_method_annotations(cm->method_annotations());
+  }
+  if (cm->has_parameter_annotations()) {
+    assert(has_parameter_annotations(), "should be allocated already");
+    set_parameter_annotations(cm->parameter_annotations());
+  }
+  if (cm->has_type_annotations()) {
+    assert(has_type_annotations(), "should be allocated already");
+    set_type_annotations(cm->type_annotations());
+  }
+  if (cm->has_default_annotations()) {
+    assert(has_default_annotations(), "should be allocated already");
+    set_default_annotations(cm->default_annotations());
+  }
+}
+
 // Printing
 
 void ConstMethod::print_on(outputStream* st) const {
--- a/src/share/vm/oops/constMethod.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/constMethod.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -280,6 +280,7 @@
   // stackmap table data
   Array<u1>* stackmap_data() const { return _stackmap_data; }
   void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }
+  void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS);
   bool has_stackmap_table() const { return _stackmap_data != NULL; }
 
   void init_fingerprint() {
@@ -440,6 +441,9 @@
     return has_default_annotations() ? default_annotations()->length() : 0;
   }
 
+  // Copy annotations from other ConstMethod
+  void copy_annotations_from(ConstMethod* cm);
+
   // byte codes
   void    set_code(address code) {
     if (code_size() > 0) {
--- a/src/share/vm/oops/constantPool.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/constantPool.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1378,12 +1378,13 @@
 
 // JVMTI GetConstantPool support
 
-// For temporary use until code is stable.
-#define DBG(code)
+// For debugging of constant pool
+const bool debug_cpool = false;
 
-static const char* WARN_MSG = "Must not be such entry!";
+#define DBG(code) do { if (debug_cpool) { (code); } } while(0)
 
 static void print_cpool_bytes(jint cnt, u1 *bytes) {
+  const char* WARN_MSG = "Must not be such entry!";
   jint size = 0;
   u2   idx1, idx2;
 
@@ -1669,8 +1670,7 @@
         idx1 = tbl->symbol_to_value(sym);
         assert(idx1 != 0, "Have not found a hashtable entry");
         Bytes::put_Java_u2((address) (bytes+1), idx1);
-        DBG(char *str = sym->as_utf8());
-        DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, str));
+        DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, sym->as_utf8()));
         break;
       }
       case JVM_CONSTANT_Fieldref:
@@ -1745,6 +1745,8 @@
   return (int)(bytes - start_bytes);
 } /* end copy_cpool_bytes */
 
+#undef DBG
+
 
 void ConstantPool::set_on_stack(const bool value) {
   if (value) {
@@ -1852,6 +1854,7 @@
   switch (tag_at(index).value()) {
     case JVM_CONSTANT_Class :
       { Klass* k = klass_at(index, CATCH);
+        guarantee(k != NULL, "need klass");
         k->print_value_on(st);
         st->print(" {0x%lx}", (address)k);
       }
--- a/src/share/vm/oops/cpCache.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/cpCache.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -44,6 +44,8 @@
 void ConstantPoolCacheEntry::initialize_entry(int index) {
   assert(0 < index && index < 0x10000, "sanity check");
   _indices = index;
+  _f1 = NULL;
+  _f2 = _flags = 0;
   assert(constant_pool_index() == index, "");
 }
 
@@ -533,13 +535,17 @@
 
 // Implementation of ConstantPoolCache
 
-ConstantPoolCache* ConstantPoolCache::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
+ConstantPoolCache* ConstantPoolCache::allocate(ClassLoaderData* loader_data,
+                                     int length,
+                                     const intStack& index_map,
+                                     const intStack& invokedynamic_map, TRAPS) {
   int size = ConstantPoolCache::size(length);
 
-  return new (loader_data, size, false, THREAD) ConstantPoolCache(length);
+  return new (loader_data, size, false, THREAD) ConstantPoolCache(length, index_map, invokedynamic_map);
 }
 
-void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invokedynamic_references_map) {
+void ConstantPoolCache::initialize(const intArray& inverse_index_map,
+                                   const intArray& invokedynamic_references_map) {
   assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache");
   for (int i = 0; i < length(); i++) {
     ConstantPoolCacheEntry* e = entry_at(i);
--- a/src/share/vm/oops/cpCache.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/cpCache.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -377,14 +377,21 @@
   debug_only(friend class ClassVerifier;)
 
   // Constructor
-  ConstantPoolCache(int length) : _length(length), _constant_pool(NULL) {
+  ConstantPoolCache(int length, const intStack& inverse_index_map,
+                    const intStack& invokedynamic_references_map) :
+                                        _length(length), _constant_pool(NULL) {
+    initialize(inverse_index_map, invokedynamic_references_map);
     for (int i = 0; i < length; i++) {
       assert(entry_at(i)->is_f1_null(), "Failed to clear?");
     }
   }
 
+  // Initialization
+  void initialize(const intArray& inverse_index_map, const intArray& invokedynamic_references_map);
  public:
-  static ConstantPoolCache* allocate(ClassLoaderData* loader_data, int length, TRAPS);
+  static ConstantPoolCache* allocate(ClassLoaderData* loader_data, int length,
+                                     const intStack& inverse_index_map,
+                                     const intStack& invokedynamic_references_map, TRAPS);
   bool is_constantPoolCache() const { return true; }
 
   int length() const                             { return _length; }
@@ -405,9 +412,6 @@
   friend class ConstantPoolCacheEntry;
 
  public:
-  // Initialization
-  void initialize(intArray& inverse_index_map, intArray& invokedynamic_references_map);
-
   // Accessors
   void set_constant_pool(ConstantPool* pool)   { _constant_pool = pool; }
   ConstantPool* constant_pool() const          { return _constant_pool; }
--- a/src/share/vm/oops/fieldInfo.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/fieldInfo.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -108,11 +108,11 @@
         return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE;
 #ifndef PRODUCT
       case FIELDINFO_TAG_TYPE_PLAIN:
-        ShouldNotReachHere2("Asking offset for the plain type field");
+        fatal("Asking offset for the plain type field");
       case FIELDINFO_TAG_TYPE_CONTENDED:
-        ShouldNotReachHere2("Asking offset for the contended type field");
+        fatal("Asking offset for the contended type field");
       case FIELDINFO_TAG_BLANK:
-        ShouldNotReachHere2("Asking offset for the blank field");
+        fatal("Asking offset for the blank field");
 #endif
     }
     ShouldNotReachHere();
@@ -128,9 +128,9 @@
         return true;
 #ifndef PRODUCT
       case FIELDINFO_TAG_OFFSET:
-        ShouldNotReachHere2("Asking contended flag for the field with offset");
+        fatal("Asking contended flag for the field with offset");
       case FIELDINFO_TAG_BLANK:
-        ShouldNotReachHere2("Asking contended flag for the blank field");
+        fatal("Asking contended flag for the blank field");
 #endif
     }
     ShouldNotReachHere();
@@ -146,9 +146,9 @@
         return _shorts[high_packed_offset];
 #ifndef PRODUCT
       case FIELDINFO_TAG_OFFSET:
-        ShouldNotReachHere2("Asking the contended group for the field with offset");
+        fatal("Asking the contended group for the field with offset");
       case FIELDINFO_TAG_BLANK:
-        ShouldNotReachHere2("Asking the contended group for the blank field");
+        fatal("Asking the contended group for the blank field");
 #endif
     }
     ShouldNotReachHere();
@@ -163,9 +163,9 @@
         return (lo >> FIELDINFO_TAG_SIZE);
 #ifndef PRODUCT
       case FIELDINFO_TAG_OFFSET:
-        ShouldNotReachHere2("Asking the field type for field with offset");
+        fatal("Asking the field type for field with offset");
       case FIELDINFO_TAG_BLANK:
-        ShouldNotReachHere2("Asking the field type for the blank field");
+        fatal("Asking the field type for the blank field");
 #endif
     }
     ShouldNotReachHere();
@@ -211,7 +211,7 @@
       case FIELDINFO_TAG_TYPE_PLAIN:
       case FIELDINFO_TAG_TYPE_CONTENDED:
       case FIELDINFO_TAG_OFFSET:
-        ShouldNotReachHere2("Setting the field type with overwriting");
+        fatal("Setting the field type with overwriting");
 #endif
     }
     ShouldNotReachHere();
@@ -226,11 +226,11 @@
         return;
 #ifndef PRODUCT
       case FIELDINFO_TAG_TYPE_CONTENDED:
-        ShouldNotReachHere2("Overwriting contended group");
+        fatal("Overwriting contended group");
       case FIELDINFO_TAG_BLANK:
-        ShouldNotReachHere2("Setting contended group for the blank field");
+        fatal("Setting contended group for the blank field");
       case FIELDINFO_TAG_OFFSET:
-        ShouldNotReachHere2("Setting contended group for field with offset");
+        fatal("Setting contended group for field with offset");
 #endif
     }
     ShouldNotReachHere();
--- a/src/share/vm/oops/generateOopMap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/generateOopMap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -762,6 +762,7 @@
 // monitor matching is purely informational and doesn't say anything
 // about the correctness of the code.
 void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) {
+  guarantee(bb != NULL, "null basicblock");
   assert(bb->is_alive(), "merging state into a dead basicblock");
 
   if (_stack_top == bb->_stack_top) {
@@ -1189,6 +1190,7 @@
 
       if (start_pc <= bci && bci < end_pc) {
         BasicBlock *excBB = get_basic_block_at(handler_pc);
+        guarantee(excBB != NULL, "no basic block for exception");
         CellTypeState *excStk = excBB->stack();
         CellTypeState *cOpStck = stack();
         CellTypeState cOpStck_0 = cOpStck[0];
@@ -1803,6 +1805,7 @@
     // possibility that this bytecode will throw an
     // exception.
     BasicBlock* bb = get_basic_block_containing(bci);
+    guarantee(bb != NULL, "no basic block for bci");
     bb->set_changed(true);
     bb->_monitor_top = bad_monitors;
 
@@ -2190,6 +2193,7 @@
 
   // Find basicblock and report results
   BasicBlock* bb = get_basic_block_containing(bci);
+  guarantee(bb != NULL, "no basic block for bci");
   assert(bb->is_reachable(), "getting result from unreachable basicblock");
   bb->set_changed(true);
   interp_bb(bb);
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -165,7 +165,8 @@
 
 volatile int InstanceKlass::_total_instanceKlass_count = 0;
 
-Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
+InstanceKlass* InstanceKlass::allocate_instance_klass(
+                                              ClassLoaderData* loader_data,
                                               int vtable_len,
                                               int itable_len,
                                               int static_field_size,
@@ -207,10 +208,35 @@
         access_flags, is_anonymous);
   }
 
+  // Check for pending exception before adding to the loader data and incrementing
+  // class count.  Can get OOM here.
+  if (HAS_PENDING_EXCEPTION) {
+    return NULL;
+  }
+
+  // Add all classes to our internal class loader list here,
+  // including classes in the bootstrap (NULL) class loader.
+  loader_data->add_class(ik);
+
   Atomic::inc(&_total_instanceKlass_count);
   return ik;
 }
 
+
+// copy method ordering from resource area to Metaspace
+void InstanceKlass::copy_method_ordering(intArray* m, TRAPS) {
+  if (m != NULL) {
+    // allocate a new array and copy contents (memcpy?)
+    _method_ordering = MetadataFactory::new_array<int>(class_loader_data(), m->length(), CHECK);
+    for (int i = 0; i < m->length(); i++) {
+      _method_ordering->at_put(i, m->at(i));
+    }
+  } else {
+    _method_ordering = Universe::the_empty_int_array();
+  }
+}
+
+
 InstanceKlass::InstanceKlass(int vtable_len,
                              int itable_len,
                              int static_field_size,
@@ -220,72 +246,116 @@
                              bool is_anonymous) {
   No_Safepoint_Verifier no_safepoint; // until k becomes parsable
 
-  int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
-                                 access_flags.is_interface(), is_anonymous);
-
-  // The sizes of these these three variables are used for determining the
-  // size of the instanceKlassOop. It is critical that these are set to the right
-  // sizes before the first GC, i.e., when we allocate the mirror.
-  this->set_vtable_length(vtable_len);
-  this->set_itable_length(itable_len);
-  this->set_static_field_size(static_field_size);
-  this->set_nonstatic_oop_map_size(nonstatic_oop_map_size);
-  this->set_access_flags(access_flags);
-  this->set_is_anonymous(is_anonymous);
-  assert(this->size() == size, "wrong size for object");
-
-  this->set_array_klasses(NULL);
-  this->set_methods(NULL);
-  this->set_method_ordering(NULL);
-  this->set_local_interfaces(NULL);
-  this->set_transitive_interfaces(NULL);
-  this->init_implementor();
-  this->set_fields(NULL, 0);
-  this->set_constants(NULL);
-  this->set_class_loader_data(NULL);
-  this->set_protection_domain(NULL);
-  this->set_signers(NULL);
-  this->set_source_file_name(NULL);
-  this->set_source_debug_extension(NULL, 0);
-  this->set_array_name(NULL);
-  this->set_inner_classes(NULL);
-  this->set_static_oop_field_count(0);
-  this->set_nonstatic_field_size(0);
-  this->set_is_marked_dependent(false);
-  this->set_init_state(InstanceKlass::allocated);
-  this->set_init_thread(NULL);
-  this->set_init_lock(NULL);
-  this->set_reference_type(rt);
-  this->set_oop_map_cache(NULL);
-  this->set_jni_ids(NULL);
-  this->set_osr_nmethods_head(NULL);
-  this->set_breakpoints(NULL);
-  this->init_previous_versions();
-  this->set_generic_signature(NULL);
-  this->release_set_methods_jmethod_ids(NULL);
-  this->release_set_methods_cached_itable_indices(NULL);
-  this->set_annotations(NULL);
-  this->set_jvmti_cached_class_field_map(NULL);
-  this->set_initial_method_idnum(0);
+  int iksize = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
+                                   access_flags.is_interface(), is_anonymous);
+
+  set_vtable_length(vtable_len);
+  set_itable_length(itable_len);
+  set_static_field_size(static_field_size);
+  set_nonstatic_oop_map_size(nonstatic_oop_map_size);
+  set_access_flags(access_flags);
+  _misc_flags = 0;  // initialize to zero
+  set_is_anonymous(is_anonymous);
+  assert(size() == iksize, "wrong size for object");
+
+  set_array_klasses(NULL);
+  set_methods(NULL);
+  set_method_ordering(NULL);
+  set_local_interfaces(NULL);
+  set_transitive_interfaces(NULL);
+  init_implementor();
+  set_fields(NULL, 0);
+  set_constants(NULL);
+  set_class_loader_data(NULL);
+  set_protection_domain(NULL);
+  set_signers(NULL);
+  set_source_file_name(NULL);
+  set_source_debug_extension(NULL, 0);
+  set_array_name(NULL);
+  set_inner_classes(NULL);
+  set_static_oop_field_count(0);
+  set_nonstatic_field_size(0);
+  set_is_marked_dependent(false);
+  set_init_state(InstanceKlass::allocated);
+  set_init_thread(NULL);
+  set_init_lock(NULL);
+  set_reference_type(rt);
+  set_oop_map_cache(NULL);
+  set_jni_ids(NULL);
+  set_osr_nmethods_head(NULL);
+  set_breakpoints(NULL);
+  init_previous_versions();
+  set_generic_signature(NULL);
+  release_set_methods_jmethod_ids(NULL);
+  release_set_methods_cached_itable_indices(NULL);
+  set_annotations(NULL);
+  set_jvmti_cached_class_field_map(NULL);
+  set_initial_method_idnum(0);
+  _dependencies = NULL;
+  set_jvmti_cached_class_field_map(NULL);
+  set_cached_class_file(NULL, 0);
+  set_initial_method_idnum(0);
+  set_minor_version(0);
+  set_major_version(0);
+  NOT_PRODUCT(_verify_count = 0;)
 
   // initialize the non-header words to zero
   intptr_t* p = (intptr_t*)this;
-  for (int index = InstanceKlass::header_size(); index < size; index++) {
+  for (int index = InstanceKlass::header_size(); index < iksize; index++) {
     p[index] = NULL_WORD;
   }
 
   // Set temporary value until parseClassFile updates it with the real instance
   // size.
-  this->set_layout_helper(Klass::instance_layout_helper(0, true));
+  set_layout_helper(Klass::instance_layout_helper(0, true));
+}
+
+
+void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
+                                       Array<Method*>* methods) {
+  if (methods != NULL && methods != Universe::the_empty_method_array()) {
+    for (int i = 0; i < methods->length(); i++) {
+      Method* method = methods->at(i);
+      if (method == NULL) continue;  // maybe null if error processing
+      // Only want to delete methods that are not executing for RedefineClasses.
+      // The previous version will point to them so they're not totally dangling
+      assert (!method->on_stack(), "shouldn't be called with methods on stack");
+      MetadataFactory::free_metadata(loader_data, method);
+    }
+    MetadataFactory::free_array<Method*>(loader_data, methods);
+  }
 }
 
+void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data,
+                                          Klass* super_klass,
+                                          Array<Klass*>* local_interfaces,
+                                          Array<Klass*>* transitive_interfaces) {
+  // Only deallocate transitive interfaces if not empty, same as super class
+  // or same as local interfaces.  See code in parseClassFile.
+  Array<Klass*>* ti = transitive_interfaces;
+  if (ti != Universe::the_empty_klass_array() && ti != local_interfaces) {
+    // check that the interfaces don't come from super class
+    Array<Klass*>* sti = (super_klass == NULL) ? NULL :
+                    InstanceKlass::cast(super_klass)->transitive_interfaces();
+    if (ti != sti) {
+      MetadataFactory::free_array<Klass*>(loader_data, ti);
+    }
+  }
+
+  // local interfaces can be empty
+  if (local_interfaces != Universe::the_empty_klass_array()) {
+    MetadataFactory::free_array<Klass*>(loader_data, local_interfaces);
+  }
+}
 
 // This function deallocates the metadata and C heap pointers that the
 // InstanceKlass points to.
 void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
 
   // Orphan the mirror first, CMS thinks it's still live.
-  java_lang_Class::set_klass(java_mirror(), NULL);
+  if (java_mirror() != NULL) {
+    java_lang_Class::set_klass(java_mirror(), NULL);
+  }
 
   // Need to take this class off the class loader data list.
   loader_data->remove_class(this);
@@ -300,17 +370,7 @@
   // reference counting symbol names.
   release_C_heap_structures();
 
-  Array<Method*>* ms = methods();
-  if (ms != Universe::the_empty_method_array()) {
-    for (int i = 0; i <= methods()->length() -1 ; i++) {
-      Method* method = methods()->at(i);
-      // Only want to delete methods that are not executing for RedefineClasses.
-      // The previous version will point to them so they're not totally dangling
-      assert (!method->on_stack(), "shouldn't be called with methods on stack");
-      MetadataFactory::free_metadata(loader_data, method);
-    }
-    MetadataFactory::free_array<Method*>(loader_data, methods());
-  }
+  deallocate_methods(loader_data, methods());
   set_methods(NULL);
 
   if (method_ordering() != Universe::the_empty_int_array()) {
@@ -327,24 +387,8 @@
   }
   set_secondary_supers(NULL);
 
-  // Only deallocate transitive interfaces if not empty, same as super class
-  // or same as local interfaces.   See code in parseClassFile.
-  Array<Klass*>* ti = transitive_interfaces();
-  if (ti != Universe::the_empty_klass_array() && ti != local_interfaces()) {
-    // check that the interfaces don't come from super class
-    Array<Klass*>* sti = (super() == NULL) ? NULL :
-       InstanceKlass::cast(super())->transitive_interfaces();
-    if (ti != sti) {
-      MetadataFactory::free_array<Klass*>(loader_data, ti);
-    }
-  }
+  deallocate_interfaces(loader_data, super(), local_interfaces(), transitive_interfaces());
   set_transitive_interfaces(NULL);
-
-  // local interfaces can be empty
-  Array<Klass*>* li = local_interfaces();
-  if (li != Universe::the_empty_klass_array()) {
-    MetadataFactory::free_array<Klass*>(loader_data, li);
-  }
   set_local_interfaces(NULL);
 
   MetadataFactory::free_array<jushort>(loader_data, fields());
@@ -352,9 +396,11 @@
 
   // If a method from a redefined class is using this constant pool, don't
   // delete it, yet.  The new class's previous version will point to this.
-  assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
-  MetadataFactory::free_metadata(loader_data, constants());
-  set_constants(NULL);
+  if (constants() != NULL) {
+    assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
+    MetadataFactory::free_metadata(loader_data, constants());
+    set_constants(NULL);
+  }
 
   if (inner_classes() != Universe::the_empty_short_array()) {
     MetadataFactory::free_array<jushort>(loader_data, inner_classes());
@@ -2170,7 +2216,11 @@
       if (impl != NULL) {
         if (!impl->is_loader_alive(is_alive)) {
           // remove this guy
-          *adr_implementor() = NULL;
+          Klass** klass = adr_implementor();
+          assert(klass != NULL, "null klass");
+          if (klass != NULL) {
+            *klass = NULL;
+          }
         }
       }
     }
@@ -2178,8 +2228,6 @@
 }
 
 void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {
-#if defined(COMPILER2) || defined(GRAAL)
-   // Currently only used by C2 and Graal
   for (int m = 0; m < methods()->length(); m++) {
     MethodData* mdo = methods()->at(m)->method_data();
     if (mdo != NULL) {
@@ -2190,15 +2238,6 @@
       }
     }
   }
-#else
-#ifdef ASSERT
-  // Verify that we haven't started to use MDOs for C1.
-  for (int m = 0; m < methods()->length(); m++) {
-    MethodData* mdo = methods()->at(m)->method_data();
-    assert(mdo == NULL, "Didn't expect C1 to use MDOs");
-  }
-#endif // ASSERT
-#endif // !COMPILER2
 }
 
 
@@ -2781,7 +2820,7 @@
   st->print(BULLET"protection domain: "); ((InstanceKlass*)this)->protection_domain()->print_value_on(st); st->cr();
   st->print(BULLET"host class:        "); host_klass()->print_value_on_maybe_null(st); st->cr();
   st->print(BULLET"signers:           "); signers()->print_value_on(st);               st->cr();
-  st->print(BULLET"init_lock:         "); ((oop)init_lock())->print_value_on(st);             st->cr();
+  st->print(BULLET"init_lock:         "); ((oop)_init_lock)->print_value_on(st);             st->cr();
   if (source_file_name() != NULL) {
     st->print(BULLET"source file:       ");
     source_file_name()->print_value_on(st);
@@ -2911,7 +2950,7 @@
   }
 }
 
-#endif
+#endif //PRODUCT
 
 void InstanceKlass::oop_print_value_on(oop obj, outputStream* st) {
   st->print("a ");
@@ -3118,7 +3157,7 @@
     Array<int>* method_ordering = this->method_ordering();
     int length = method_ordering->length();
     if (JvmtiExport::can_maintain_original_method_order() ||
-        (UseSharedSpaces && length != 0)) {
+        ((UseSharedSpaces || DumpSharedSpaces) && length != 0)) {
       guarantee(length == methods()->length(), "invalid method ordering length");
       jlong sum = 0;
       for (int j = 0; j < length; j++) {
--- a/src/share/vm/oops/instanceKlass.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/instanceKlass.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -147,7 +147,8 @@
                 AccessFlags access_flags,
                 bool is_anonymous);
  public:
-  static Klass* allocate_instance_klass(ClassLoaderData* loader_data,
+  static InstanceKlass* allocate_instance_klass(
+                                          ClassLoaderData* loader_data,
                                           int vtable_len,
                                           int itable_len,
                                           int static_field_size,
@@ -266,8 +267,9 @@
   u1              _init_state;                    // state of class
   u1              _reference_type;                // reference type
 
+  JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map;  // JVMTI: used during heap iteration
 
-  JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map;  // JVMTI: used during heap iteration
+  NOT_PRODUCT(int _verify_count;)  // to avoid redundant verifies
 
   // Method array.
   Array<Method*>* _methods;
@@ -356,16 +358,19 @@
   // method ordering
   Array<int>* method_ordering() const     { return _method_ordering; }
   void set_method_ordering(Array<int>* m) { _method_ordering = m; }
+  void copy_method_ordering(intArray* m, TRAPS);
 
   // interfaces
   Array<Klass*>* local_interfaces() const          { return _local_interfaces; }
   void set_local_interfaces(Array<Klass*>* a)      {
     guarantee(_local_interfaces == NULL || a == NULL, "Just checking");
     _local_interfaces = a; }
+
   Array<Klass*>* transitive_interfaces() const     { return _transitive_interfaces; }
   void set_transitive_interfaces(Array<Klass*>* a) {
     guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking");
-    _transitive_interfaces = a; }
+    _transitive_interfaces = a;
+  }
 
  private:
   friend class fieldDescriptor;
@@ -381,10 +386,9 @@
   int java_fields_count() const           { return (int)_java_fields_count; }
 
   Array<u2>* fields() const            { return _fields; }
-
   void set_fields(Array<u2>* f, u2 java_fields_count) {
     guarantee(_fields == NULL || f == NULL, "Just checking");
-    _fields =  f;
+    _fields = f;
     _java_fields_count = java_fields_count;
   }
 
@@ -536,7 +540,9 @@
     assert(is_anonymous(), "not anonymous");
     Klass** addr = (Klass**)adr_host_klass();
     assert(addr != NULL, "no reversed space");
-    *addr = host;
+    if (addr != NULL) {
+      *addr = host;
+    }
   }
   bool is_anonymous() const                {
     return (_misc_flags & _misc_is_anonymous) != 0;
@@ -586,7 +592,7 @@
 
   // symbol unloading support (refcount already added)
   Symbol* array_name()                     { return _array_name; }
-  void set_array_name(Symbol* name)        { assert(_array_name == NULL, "name already created"); _array_name = name; }
+  void set_array_name(Symbol* name)        { assert(_array_name == NULL  || name == NULL, "name already created"); _array_name = name; }
 
   // nonstatic oop-map blocks
   static int nonstatic_oop_map_size(unsigned int oop_map_count) {
@@ -758,7 +764,10 @@
   void set_implementor(Klass* k) {
     assert(is_interface(), "not interface");
     Klass** addr = adr_implementor();
-    *addr = k;
+    assert(addr != NULL, "null addr");
+    if (addr != NULL) {
+      *addr = k;
+    }
   }
 
   int  nof_implementors() const       {
@@ -909,8 +918,15 @@
   void clean_method_data(BoolObjectClosure* is_alive);
 
   // Explicit metaspace deallocation of fields
-  // For RedefineClasses, we need to deallocate instanceKlasses
+  // For RedefineClasses and class file parsing errors, we need to deallocate
+  // instanceKlasses and the metadata they point to.
   void deallocate_contents(ClassLoaderData* loader_data);
+  static void deallocate_methods(ClassLoaderData* loader_data,
+                                 Array<Method*>* methods);
+  void static deallocate_interfaces(ClassLoaderData* loader_data,
+                                    Klass* super_klass,
+                                    Array<Klass*>* local_interfaces,
+                                    Array<Klass*>* transitive_interfaces);
 
   // The constant pool is on stack if any of the methods are executing or
   // referenced by handles.
--- a/src/share/vm/oops/klass.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/klass.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -146,16 +146,16 @@
 Klass::Klass() {
   Klass* k = this;
 
-  { // Preinitialize supertype information.
-    // A later call to initialize_supers() may update these settings:
-    set_super(NULL);
-    for (juint i = 0; i < Klass::primary_super_limit(); i++) {
-      _primary_supers[i] = NULL;
-    }
-    set_secondary_supers(NULL);
-    _primary_supers[0] = k;
-    set_super_check_offset(in_bytes(primary_supers_offset()));
+  // Preinitialize supertype information.
+  // A later call to initialize_supers() may update these settings:
+  set_super(NULL);
+  for (juint i = 0; i < Klass::primary_super_limit(); i++) {
+    _primary_supers[i] = NULL;
   }
+  set_secondary_supers(NULL);
+  set_secondary_super_cache(NULL);
+  _primary_supers[0] = k;
+  set_super_check_offset(in_bytes(primary_supers_offset()));
 
   set_java_mirror(NULL);
   set_modifier_flags(0);
@@ -486,6 +486,12 @@
 }
 
 void Klass::remove_unshareable_info() {
+  if (!DumpSharedSpaces) {
+    // Clean up after OOM during class loading
+    if (class_loader_data() != NULL) {
+      class_loader_data()->remove_class(this);
+    }
+  }
   set_subklass(NULL);
   set_next_sibling(NULL);
   // Clear the java mirror
--- a/src/share/vm/oops/klass.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/klass.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -79,7 +79,6 @@
 //    [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]
@@ -176,10 +175,6 @@
   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
 
   TRACE_DEFINE_KLASS_TRACE_ID;
--- a/src/share/vm/oops/klassVtable.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/klassVtable.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -327,11 +327,11 @@
 
           if (target_loader() != super_loader()) {
             ResourceMark rm(THREAD);
-            char* failed_type_name =
+            Symbol* failed_type_symbol =
               SystemDictionary::check_signature_loaders(signature, target_loader,
                                                         super_loader, true,
                                                         CHECK_(false));
-            if (failed_type_name != NULL) {
+            if (failed_type_symbol != NULL) {
               const char* msg = "loader constraint violation: when resolving "
                 "overridden method \"%s\" the class loader (instance"
                 " of %s) of the current class, %s, and its superclass loader "
@@ -341,6 +341,7 @@
               const char* loader1 = SystemDictionary::loader_name(target_loader());
               char* current = _klass->name()->as_C_string();
               const char* loader2 = SystemDictionary::loader_name(super_loader());
+              char* failed_type_name = failed_type_symbol->as_C_string();
               size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
                 strlen(current) + strlen(loader2) + strlen(failed_type_name);
               char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
@@ -787,12 +788,12 @@
         Handle method_holder_loader (THREAD, target->method_holder()->class_loader());
         if (method_holder_loader() != interface_loader()) {
           ResourceMark rm(THREAD);
-          char* failed_type_name =
+          Symbol* failed_type_symbol =
             SystemDictionary::check_signature_loaders(method_signature,
                                                       method_holder_loader,
                                                       interface_loader,
                                                       true, CHECK);
-          if (failed_type_name != NULL) {
+          if (failed_type_symbol != NULL) {
             const char* msg = "loader constraint violation in interface "
               "itable initialization: when resolving method \"%s\" the class"
               " loader (instance of %s) of the current class, %s, "
@@ -804,6 +805,7 @@
             char* current = klass->name()->as_C_string();
             const char* loader2 = SystemDictionary::loader_name(interface_loader());
             char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string();
+            char* failed_type_name = failed_type_symbol->as_C_string();
             size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
               strlen(current) + strlen(loader2) + strlen(iface) +
               strlen(failed_type_name);
--- a/src/share/vm/oops/method.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/method.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -77,22 +77,19 @@
   return new (loader_data, size, false, THREAD) Method(cm, access_flags, size);
 }
 
-Method::Method(ConstMethod* xconst,
-                             AccessFlags access_flags, int size) {
+Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) {
   No_Safepoint_Verifier no_safepoint;
   set_constMethod(xconst);
   set_access_flags(access_flags);
   set_method_size(size);
-  set_name_index(0);
-  set_signature_index(0);
 #ifdef CC_INTERP
   set_result_index(T_VOID);
 #endif
-  set_constants(NULL);
-  set_max_stack(0);
-  set_max_locals(0);
   set_intrinsic_id(vmIntrinsics::_none);
   set_jfr_towrite(false);
+  set_force_inline(false);
+  set_hidden(false);
+  set_dont_inline(false);
   set_method_data(NULL);
   set_interpreter_throwout_count(0);
   set_vtable_index(Method::garbage_vtable_index);
@@ -725,7 +722,7 @@
   if (number_of_breakpoints() > 0)
     return true;
   if (is_method_handle_intrinsic())
-    return !is_synthetic();  // the generated adapters must be compiled
+    return !is_synthetic() && intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;  // the generated adapters must be compiled
   if (comp_level == CompLevel_any)
     return is_not_c1_compilable() || is_not_c2_compilable();
   if (is_c1_compile(comp_level))
@@ -806,7 +803,15 @@
   backedge_counter()->reset();
   _adapter = NULL;
   _from_compiled_entry = NULL;
-  assert(_method_data == NULL, "unexpected method data?");
+
+  // In case of DumpSharedSpaces, _method_data should always be NULL.
+  //
+  // During runtime (!DumpSharedSpaces), when we are cleaning a
+  // shared class that failed to load, this->link_method() may
+  // have already been called (before an exception happened), so
+  // this->_method_data may not be NULL.
+  assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?");
+
   set_method_data(NULL);
   set_interpreter_throwout_count(0);
   set_interpreter_invocation_count(0);
@@ -846,6 +851,14 @@
 
   // ONLY USE the h_method now as make_adapter may have blocked
 
+#ifdef GRAAL
+  // Check for special intrinsic that executes a compiled method.
+  if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // Actively install the stub for calling the intrinsic from compiled code.
+    CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier,
+                                  methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK);
+  }
+#endif
 }
 
 address Method::make_adapters(methodHandle mh, TRAPS) {
@@ -967,6 +980,32 @@
   return false;
 }
 
+
+/**
+ *  Returns true if this is one of the specially treated methods for
+ *  security related stack walks (like Reflection.getCallerClass).
+ */
+bool Method::is_ignored_by_security_stack_walk() const {
+  const bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
+
+  assert(intrinsic_id() != vmIntrinsics::_invoke || Universe::reflect_invoke_cache()->is_same_method((Method*)this), "sanity");
+  if (intrinsic_id() == vmIntrinsics::_invoke) {
+    // This is Method.invoke() -- ignore it
+    return true;
+  }
+  if (use_new_reflection &&
+      method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
+    // This is an auxilary frame -- ignore it
+    return true;
+  }
+  if (is_method_handle_intrinsic() || is_compiled_lambda_form()) {
+    // This is an internal adapter frame for method handles -- ignore it
+    return true;
+  }
+  return false;
+}
+
+
 // Constant pool structure for invoke methods:
 enum {
   _imcp_invoke_name = 1,        // utf8: 'invokeExact', etc.
@@ -983,8 +1022,8 @@
 // Test if this method is an internal MH primitive method.
 bool Method::is_method_handle_intrinsic() const {
   vmIntrinsics::ID iid = intrinsic_id();
-  return (MethodHandles::is_signature_polymorphic(iid) &&
-          MethodHandles::is_signature_polymorphic_intrinsic(iid));
+  return ((MethodHandles::is_signature_polymorphic(iid) &&
+          MethodHandles::is_signature_polymorphic_intrinsic(iid))) || iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;
 }
 
 bool Method::has_member_arg() const {
@@ -1170,6 +1209,8 @@
     newm->set_stackmap_data(stackmap_data);
   }
 
+  // copy annotations over to new method
+  newcm->copy_annotations_from(cm);
   return newm;
 }
 
@@ -1178,13 +1219,13 @@
   // because we are not loading from core libraries
   // exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
   // which does not use the class default class loader so we check for its loader here
-  if ((InstanceKlass::cast(holder)->class_loader() != NULL) &&
-       InstanceKlass::cast(holder)->class_loader()->klass()->name() != vmSymbols::sun_misc_Launcher_ExtClassLoader()) {
+  InstanceKlass* ik = InstanceKlass::cast(holder);
+  if ((ik->class_loader() != NULL) && !SystemDictionary::is_ext_class_loader(ik->class_loader())) {
     return vmSymbols::NO_SID;   // regardless of name, no intrinsics here
   }
 
   // see if the klass name is well-known:
-  Symbol* klass_name = InstanceKlass::cast(holder)->name();
+  Symbol* klass_name = ik->name();
   return vmSymbols::find_sid(klass_name);
 }
 
--- a/src/share/vm/oops/method.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/method.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -118,11 +118,12 @@
 #endif
   u2                _method_size;                // size of this object
   u1                _intrinsic_id;               // vmSymbols::intrinsic_id (0 == _none)
-  u1                _jfr_towrite  : 1,           // Flags
-                    _force_inline : 1,
-                    _hidden       : 1,
-                    _dont_inline  : 1,
-                                  : 4;
+  u1                _jfr_towrite      : 1,       // Flags
+                    _caller_sensitive : 1,
+                    _force_inline     : 1,
+                    _hidden           : 1,
+                    _dont_inline      : 1,
+                                      : 3;
   u2                _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
   u2                _number_of_breakpoints;      // fullspeed debugging support
   InvocationCounter _invocation_counter;         // Incremented before each activation of the method - used to trigger frequency-based optimizations
@@ -636,6 +637,9 @@
   // Reflection support
   bool is_overridden_in(Klass* k) const;
 
+  // Stack walking support
+  bool is_ignored_by_security_stack_walk() const;
+
   // JSR 292 support
   bool is_method_handle_intrinsic() const;          // MethodHandles::is_signature_polymorphic_intrinsic(intrinsic_id)
   bool is_compiled_lambda_form() const;             // intrinsic_id() == vmIntrinsics::_compiledLambdaForm
@@ -723,15 +727,16 @@
   void init_intrinsic_id();     // updates from _none if a match
   static vmSymbols::SID klass_id_for_intrinsics(Klass* holder);
 
-  bool jfr_towrite()                 { return _jfr_towrite; }
-  void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
-
-  bool     force_inline()       { return _force_inline;     }
-  void set_force_inline(bool x) {        _force_inline = x; }
-  bool     dont_inline()        { return _dont_inline;      }
-  void set_dont_inline(bool x)  {        _dont_inline = x;  }
-  bool  is_hidden()             { return _hidden;           }
-  void set_hidden(bool x)       {        _hidden = x;       }
+  bool     jfr_towrite()            { return _jfr_towrite;          }
+  void set_jfr_towrite(bool x)      {        _jfr_towrite = x;      }
+  bool     caller_sensitive()       { return _caller_sensitive;     }
+  void set_caller_sensitive(bool x) {        _caller_sensitive = x; }
+  bool     force_inline()           { return _force_inline;         }
+  void set_force_inline(bool x)     {        _force_inline = x;     }
+  bool     dont_inline()            { return _dont_inline;          }
+  void set_dont_inline(bool x)      {        _dont_inline = x;      }
+  bool  is_hidden()                 { return _hidden;               }
+  void set_hidden(bool x)           {        _hidden = x;           }
   ConstMethod::MethodType method_type() const {
       return _constMethod->method_type();
   }
@@ -771,15 +776,19 @@
   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(); }
-  void set_not_c1_compilable()                {       _access_flags.set_not_c1_compilable();  }
-  bool  is_not_c2_compilable() const          { return access_flags().is_not_c2_compilable(); }
-  void set_not_c2_compilable()                {       _access_flags.set_not_c2_compilable();  }
+  bool   is_not_c1_compilable() const         { return access_flags().is_not_c1_compilable();  }
+  void  set_not_c1_compilable()               {       _access_flags.set_not_c1_compilable();   }
+  void clear_not_c1_compilable()              {       _access_flags.clear_not_c1_compilable(); }
+  bool   is_not_c2_compilable() const         { return access_flags().is_not_c2_compilable();  }
+  void  set_not_c2_compilable()               {       _access_flags.set_not_c2_compilable();   }
+  void clear_not_c2_compilable()              {       _access_flags.clear_not_c2_compilable(); }
 
-  bool  is_not_c1_osr_compilable() const      { return is_not_c1_compilable(); }  // don't waste an accessFlags bit
-  void set_not_c1_osr_compilable()            {       set_not_c1_compilable(); }  // don't waste an accessFlags bit
-  bool  is_not_c2_osr_compilable() const      { return access_flags().is_not_c2_osr_compilable(); }
-  void set_not_c2_osr_compilable()            {       _access_flags.set_not_c2_osr_compilable();  }
+  bool    is_not_c1_osr_compilable() const    { return is_not_c1_compilable(); }  // don't waste an accessFlags bit
+  void   set_not_c1_osr_compilable()          {       set_not_c1_compilable(); }  // don't waste an accessFlags bit
+  void clear_not_c1_osr_compilable()          {     clear_not_c1_compilable(); }  // don't waste an accessFlags bit
+  bool   is_not_c2_osr_compilable() const     { return access_flags().is_not_c2_osr_compilable();  }
+  void  set_not_c2_osr_compilable()           {       _access_flags.set_not_c2_osr_compilable();   }
+  void clear_not_c2_osr_compilable()          {       _access_flags.clear_not_c2_osr_compilable(); }
 
   // Background compilation support
   bool queued_for_compilation() const  { return access_flags().queued_for_compilation(); }
--- a/src/share/vm/oops/methodData.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/methodData.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -392,6 +392,9 @@
 }
 
 int MethodData::bytecode_cell_count(Bytecodes::Code code) {
+#if defined(COMPILER1) && !(defined(COMPILER2) || defined(GRAAL))
+  return no_profile_data;
+#else
   switch (code) {
   case Bytecodes::_checkcast:
   case Bytecodes::_instanceof:
@@ -438,6 +441,7 @@
     return variable_cell_count;
   }
   return no_profile_data;
+#endif
 }
 
 // Compute the size of the profiling information corresponding to
@@ -521,6 +525,9 @@
 // the segment in bytes.
 int MethodData::initialize_data(BytecodeStream* stream,
                                        int data_index) {
+#if defined(COMPILER1) && !(defined(COMPILER2) || defined(GRAAL))
+  return 0;
+#else
   int cell_count = -1;
   int tag = DataLayout::no_tag;
   DataLayout* data_layout = data_layout_at(data_index);
@@ -599,6 +606,7 @@
     assert(!bytecode_has_profile(c), "agree w/ !BHP");
     return 0;
   }
+#endif
 }
 
 // Get the data at an arbitrary (sort of) data index.
@@ -668,31 +676,14 @@
   No_Safepoint_Verifier no_safepoint;  // init function atomic wrt GC
   ResourceMark rm;
 
-  if (TieredCompilation) {
-    _invocation_counter.init();
-    _backedge_counter.init();
-    _invocation_counter_start = 0;
-    _backedge_counter_start = 0;
-    _num_loops = 0;
-    _num_blocks = 0;
-    _highest_comp_level = 0;
-    _highest_osr_comp_level = 0;
-    _would_profile = true;
-  }
+  init();
   set_creation_mileage(mileage_of(method()));
 
-  // Initialize flags and trap history.
-  _nof_decompiles = 0;
-  _nof_overflow_recompiles = 0;
-  _nof_overflow_traps = 0;
-  assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align");
-  Copy::zero_to_words((HeapWord*) &_trap_hist,
-                      sizeof(_trap_hist) / sizeof(HeapWord));
-
   // Go through the bytecodes and allocate and initialize the
   // corresponding data cells.
   int data_size = 0;
   int empty_bc_count = 0;  // number of bytecodes lacking data
+  _data[0] = 0;  // apparently not set below.
   BytecodeStream stream(method());
   Bytecodes::Code c;
   while ((c = stream.next()) >= 0) {
@@ -734,6 +725,27 @@
   set_size(object_size);
 }
 
+void MethodData::init() {
+  _invocation_counter.init();
+  _backedge_counter.init();
+  _invocation_counter_start = 0;
+  _backedge_counter_start = 0;
+  _num_loops = 0;
+  _num_blocks = 0;
+  _highest_comp_level = 0;
+  _highest_osr_comp_level = 0;
+  _would_profile = true;
+
+  // Initialize flags and trap history.
+  _nof_decompiles = 0;
+  _nof_overflow_recompiles = 0;
+  _nof_overflow_traps = 0;
+  clear_escape_info();
+  assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align");
+  Copy::zero_to_words((HeapWord*) &_trap_hist,
+                      sizeof(_trap_hist) / sizeof(HeapWord));
+}
+
 bool MethodData::is_empty_data(int size_in_bytes, Bytecodes::Code code) {
 #ifdef GRAAL
   return size_in_bytes == 0 && Bytecodes::can_trap(code);
--- a/src/share/vm/oops/methodData.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/methodData.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1304,7 +1304,10 @@
   static bool bytecode_has_profile(Bytecodes::Code code) {
     return bytecode_cell_count(code) != no_profile_data;
   }
-  
+
+  // reset into original state
+  void init();
+
   // My size
   int size_in_bytes() const { return _size; }
   int size() const    { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); }
@@ -1384,6 +1387,7 @@
   intx arg_stack()                               { return _arg_stack; }
   intx arg_returned()                            { return _arg_returned; }
   uint arg_modified(int a)                       { ArgInfoData *aid = arg_info();
+                                                   assert(aid != NULL, "arg_info must be not null");
                                                    assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
                                                    return aid->arg_modified(a); }
 
@@ -1392,8 +1396,8 @@
   void set_arg_stack(intx v)                     { _arg_stack = v; }
   void set_arg_returned(intx v)                  { _arg_returned = v; }
   void set_arg_modified(int a, uint v)           { ArgInfoData *aid = arg_info();
+                                                   assert(aid != NULL, "arg_info must be not null");
                                                    assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
-
                                                    aid->set_arg_modified(a, v); }
 
   void clear_escape_info()                       { _eflags = _arg_local = _arg_stack = _arg_returned = 0; }
--- a/src/share/vm/oops/symbol.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/symbol.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -27,6 +27,7 @@
 #include "classfile/altHashing.hpp"
 #include "classfile/classLoaderData.hpp"
 #include "oops/symbol.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -161,7 +162,7 @@
   const char *ptr = (const char *)&_body[0];
   int quoted_length = UTF8::quoted_ascii_length(ptr, utf8_length());
   char* result = NEW_RESOURCE_ARRAY(char, quoted_length + 1);
-  UTF8::as_quoted_ascii(ptr, result, quoted_length + 1);
+  UTF8::as_quoted_ascii(ptr, utf8_length(), result, quoted_length + 1);
   return result;
 }
 
@@ -210,6 +211,28 @@
   return AltHashing::murmur3_32(seed, (const jbyte*)as_C_string(), utf8_length());
 }
 
+void Symbol::increment_refcount() {
+  // Only increment the refcount if positive.  If negative either
+  // overflow has occurred or it is a permanent symbol in a read only
+  // shared archive.
+  if (_refcount >= 0) {
+    Atomic::inc(&_refcount);
+    NOT_PRODUCT(Atomic::inc(&_total_count);)
+  }
+}
+
+void Symbol::decrement_refcount() {
+  if (_refcount >= 0) {
+    Atomic::dec(&_refcount);
+#ifdef ASSERT
+    if (_refcount < 0) {
+      print();
+      assert(false, "reference count underflow for symbol");
+    }
+#endif
+  }
+}
+
 void Symbol::print_on(outputStream* st) const {
   if (this == NULL) {
     st->print_cr("NULL");
--- a/src/share/vm/oops/symbol.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/oops/symbol.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -27,7 +27,6 @@
 
 #include "utilities/utf8.hpp"
 #include "memory/allocation.hpp"
-#include "runtime/atomic.hpp"
 
 // A Symbol is a canonicalized string.
 // All Symbols reside in global SymbolTable and are reference counted.
@@ -150,8 +149,8 @@
 
   // Reference counting.  See comments above this class for when to use.
   int refcount() const      { return _refcount; }
-  inline void increment_refcount();
-  inline void decrement_refcount();
+  void increment_refcount();
+  void decrement_refcount();
 
   int byte_at(int index) const {
     assert(index >=0 && index < _length, "symbol index overflow");
@@ -232,26 +231,4 @@
  return (((uintptr_t)this < (uintptr_t)other) ? -1
    : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
 }
-
-inline void Symbol::increment_refcount() {
-  // Only increment the refcount if positive.  If negative either
-  // overflow has occurred or it is a permanent symbol in a read only
-  // shared archive.
-  if (_refcount >= 0) {
-    Atomic::inc(&_refcount);
-    NOT_PRODUCT(Atomic::inc(&_total_count);)
-  }
-}
-
-inline void Symbol::decrement_refcount() {
-  if (_refcount >= 0) {
-    Atomic::dec(&_refcount);
-#ifdef ASSERT
-    if (_refcount < 0) {
-      print();
-      assert(false, "reference count underflow for symbol");
-    }
-#endif
-  }
-}
 #endif // SHARE_VM_OOPS_SYMBOL_HPP
--- a/src/share/vm/opto/block.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/block.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1028,26 +1028,6 @@
 }
 
 #ifndef PRODUCT
-static void edge_dump(GrowableArray<CFGEdge *> *edges) {
-  tty->print_cr("---- Edges ----");
-  for (int i = 0; i < edges->length(); i++) {
-    CFGEdge *e = edges->at(i);
-    if (e != NULL) {
-      edges->at(i)->dump();
-    }
-  }
-}
-
-static void trace_dump(Trace *traces[], int count) {
-  tty->print_cr("---- Traces ----");
-  for (int i = 0; i < count; i++) {
-    Trace *tr = traces[i];
-    if (tr != NULL) {
-      tr->dump();
-    }
-  }
-}
-
 void Trace::dump( ) const {
   tty->print_cr("Trace (freq %f)", first_block()->_freq);
   for (Block *b = first_block(); b != NULL; b = next(b)) {
--- a/src/share/vm/opto/bytecodeInfo.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -157,9 +157,10 @@
   } else {
     // 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)
+        callee_method->instructions_size() > inline_small_code_size) {
       set_msg("already compiled into a medium method");
       return false;
+    }
   }
   if (size > max_inline_size) {
     if (max_inline_size > default_max_inline_size) {
--- a/src/share/vm/opto/c2_globals.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/c2_globals.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -54,6 +54,12 @@
 
 #define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \
                                                                             \
+  develop(bool, StressLCM, false,                                           \
+          "Randomize instruction scheduling in LCM")                        \
+                                                                            \
+  develop(bool, StressGCM, false,                                           \
+          "Randomize instruction scheduling in GCM")                        \
+                                                                            \
   notproduct(intx, CompileZapFirst, 0,                                      \
           "If +ZapDeadCompiledLocals, "                                     \
           "skip this many before compiling in zap calls")                   \
--- a/src/share/vm/opto/chaitin.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/chaitin.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -187,31 +187,6 @@
 #endif
 };
 
-//------------------------------LRG_List---------------------------------------
-// Map Node indices to Live RanGe indices.
-// Array lookup in the optimized case.
-class LRG_List : public ResourceObj {
-  friend class VMStructs;
-  uint _cnt, _max;
-  uint* _lidxs;
-  ReallocMark _nesting;         // assertion check for reallocations
-public:
-  LRG_List( uint max );
-
-  uint lookup( uint nidx ) const {
-    return _lidxs[nidx];
-  }
-  uint operator[] (uint nidx) const { return lookup(nidx); }
-
-  void map( uint nidx, uint lidx ) {
-    assert( nidx < _cnt, "oob" );
-    _lidxs[nidx] = lidx;
-  }
-  void extend( uint nidx, uint lidx );
-
-  uint Size() const { return _cnt; }
-};
-
 //------------------------------IFG--------------------------------------------
 //                         InterFerence Graph
 // An undirected graph implementation.  Created with a fixed number of
--- a/src/share/vm/opto/compile.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/compile.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -892,7 +892,7 @@
   : Phase(Compiler),
     _env(ci_env),
     _log(ci_env->log()),
-    _compile_id(-1),
+    _compile_id(0),
     _save_argument_registers(save_arg_registers),
     _method(NULL),
     _stub_name(stub_name),
@@ -2326,12 +2326,14 @@
   int  get_inner_loop_count() const { return _inner_loop_count; }
 };
 
+#ifdef ASSERT
 static bool oop_offset_is_sane(const TypeInstPtr* tp) {
   ciInstanceKlass *k = tp->klass()->as_instance_klass();
   // Make sure the offset goes inside the instance layout.
   return k->contains_field_offset(tp->offset());
   // Note that OffsetBot and OffsetTop are very negative.
 }
+#endif
 
 // Eliminate trivially redundant StoreCMs and accumulate their
 // precedence edges.
@@ -2899,6 +2901,13 @@
       }
     }
     break;
+  case Op_MemBarStoreStore:
+    // Break the link with AllocateNode: it is no longer useful and
+    // confuses register allocation.
+    if (n->req() > MemBarNode::Precedent) {
+      n->set_req(MemBarNode::Precedent, top());
+    }
+    break;
   default:
     assert( !n->is_Call(), "" );
     assert( !n->is_Mem(), "" );
@@ -3669,3 +3678,38 @@
     n->set_req(0, NULL);
   }
 }
+
+// Auxiliary method to support randomized stressing/fuzzing.
+//
+// This method can be called the arbitrary number of times, with current count
+// as the argument. The logic allows selecting a single candidate from the
+// running list of candidates as follows:
+//    int count = 0;
+//    Cand* selected = null;
+//    while(cand = cand->next()) {
+//      if (randomized_select(++count)) {
+//        selected = cand;
+//      }
+//    }
+//
+// Including count equalizes the chances any candidate is "selected".
+// This is useful when we don't have the complete list of candidates to choose
+// from uniformly. In this case, we need to adjust the randomicity of the
+// selection, or else we will end up biasing the selection towards the latter
+// candidates.
+//
+// Quick back-envelope calculation shows that for the list of n candidates
+// the equal probability for the candidate to persist as "best" can be
+// achieved by replacing it with "next" k-th candidate with the probability
+// of 1/k. It can be easily shown that by the end of the run, the
+// probability for any candidate is converged to 1/n, thus giving the
+// uniform distribution among all the candidates.
+//
+// We don't care about the domain size as long as (RANDOMIZED_DOMAIN / count) is large.
+#define RANDOMIZED_DOMAIN_POW 29
+#define RANDOMIZED_DOMAIN (1 << RANDOMIZED_DOMAIN_POW)
+#define RANDOMIZED_DOMAIN_MASK ((1 << (RANDOMIZED_DOMAIN_POW + 1)) - 1)
+bool Compile::randomized_select(int count) {
+  assert(count > 0, "only positive");
+  return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
+}
--- a/src/share/vm/opto/compile.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/compile.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -678,6 +678,7 @@
   void         record_dead_node(uint idx)  { if (_dead_node_list.test_set(idx)) return;
                                              _dead_node_count++;
                                            }
+  bool         is_dead_node(uint idx)      { return _dead_node_list.test(idx) != 0; }
   uint         dead_node_count()           { return _dead_node_count; }
   void         reset_dead_node_list()      { _dead_node_list.Reset();
                                              _dead_node_count = 0;
@@ -1086,6 +1087,9 @@
 
   // Definitions of pd methods
   static void pd_compiler2_init();
+
+  // Auxiliary method for randomized fuzzing/stressing
+  static bool randomized_select(int count);
 };
 
 #endif // SHARE_VM_OPTO_COMPILE_HPP
--- a/src/share/vm/opto/connode.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/connode.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -465,29 +465,6 @@
   return (phase->type(in(1)) == phase->type(this)) ? in(1) : this;
 }
 
-// Determine whether "n" is a node which can cause an alias of one of its inputs.  Node types
-// which can create aliases are: CheckCastPP, Phi, and any store (if there is also a load from
-// the location.)
-// Note:  this checks for aliases created in this compilation, not ones which may
-//        be potentially created at call sites.
-static bool can_cause_alias(Node *n, PhaseTransform *phase) {
-  bool possible_alias = false;
-
-  if (n->is_Store()) {
-    possible_alias = !n->as_Store()->value_never_loaded(phase);
-  } else {
-    int opc = n->Opcode();
-    possible_alias = n->is_Phi() ||
-        opc == Op_CheckCastPP ||
-        opc == Op_StorePConditional ||
-        opc == Op_CompareAndSwapP ||
-        opc == Op_CompareAndSwapN ||
-        opc == Op_GetAndSetP ||
-        opc == Op_GetAndSetN;
-  }
-  return possible_alias;
-}
-
 //------------------------------Value------------------------------------------
 // Take 'join' of input and cast-up type, unless working with an Interface
 const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const {
--- a/src/share/vm/opto/gcm.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/gcm.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1046,6 +1046,8 @@
   }
 #endif
 
+  int cand_cnt = 0;  // number of candidates tried
+
   // Walk up the dominator tree from LCA (Lowest common ancestor) to
   // the earliest legal location.  Capture the least execution frequency.
   while (LCA != early) {
@@ -1071,8 +1073,11 @@
         LCA->_pre_order, LCA->_nodes[0]->_idx, start_lat, end_idx, end_lat, LCA_freq);
     }
 #endif
+    cand_cnt++;
     if (LCA_freq < least_freq              || // Better Frequency
-        ( !in_latency                   &&    // No block containing latency
+        (StressGCM && Compile::randomized_select(cand_cnt)) || // Should be randomly accepted in stress mode
+         (!StressGCM                    &&    // Otherwise, choose with latency
+          !in_latency                   &&    // No block containing latency
           LCA_freq < least_freq * delta &&    // No worse frequency
           target >= end_lat             &&    // within latency range
           !self->is_iteratively_computed() )  // But don't hoist IV increments
@@ -1210,7 +1215,8 @@
     }
 
     // If there is no opportunity to hoist, then we're done.
-    bool try_to_hoist = (LCA != early);
+    // In stress mode, try to hoist even the single operations.
+    bool try_to_hoist = StressGCM || (LCA != early);
 
     // Must clone guys stay next to use; no hoisting allowed.
     // Also cannot hoist guys that alter memory or are otherwise not
--- a/src/share/vm/opto/graphKit.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/graphKit.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -3445,7 +3445,6 @@
 
 void GraphKit::final_sync(IdealKit& ideal) {
   // Final sync IdealKit and graphKit.
-  __ drain_delay_transform();
   sync_kit(ideal);
 }
 
--- a/src/share/vm/opto/idealKit.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/idealKit.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -48,9 +48,9 @@
   _cvstate = NULL;
   // We can go memory state free or else we need the entire memory state
   assert(_initial_memory == NULL || _initial_memory->Opcode() == Op_MergeMem, "memory must be pre-split");
+  assert(!_gvn.is_IterGVN(), "IdealKit can't be used during Optimize phase");
   int init_size = 5;
   _pending_cvstates = new (C->node_arena()) GrowableArray<Node*>(C->node_arena(), init_size, 0, 0);
-  _delay_transform  = new (C->node_arena()) GrowableArray<Node*>(C->node_arena(), init_size, 0, 0);
   DEBUG_ONLY(_state = new (C->node_arena()) GrowableArray<int>(C->node_arena(), init_size, 0, 0));
   if (!has_declarations) {
      declarations_done();
@@ -296,19 +296,16 @@
     return delay_transform(n);
   } else {
     n = gvn().transform(n);
-    if (!gvn().is_IterGVN()) {
-      C->record_for_igvn(n);
-    }
+    C->record_for_igvn(n);
     return n;
   }
 }
 
 //-----------------------------delay_transform-----------------------------------
 Node* IdealKit::delay_transform(Node* n) {
-  if (!gvn().is_IterGVN() || !gvn().is_IterGVN()->delay_transform()) {
-    gvn().set_type(n, n->bottom_type());
-  }
-  _delay_transform->push(n);
+  // Delay transform until IterativeGVN
+  gvn().set_type(n, n->bottom_type());
+  C->record_for_igvn(n);
   return n;
 }
 
@@ -332,17 +329,6 @@
   for (uint i = 0; i < m->req(); i++) m->set_req(i, NULL);
 }
 
-//-----------------------------drain_delay_transform----------------------------
-void IdealKit::drain_delay_transform() {
-  while (_delay_transform->length() > 0) {
-    Node* n = _delay_transform->pop();
-    gvn().transform(n);
-    if (!gvn().is_IterGVN()) {
-      C->record_for_igvn(n);
-    }
-  }
-}
-
 //-----------------------------IdealVariable----------------------------
 IdealVariable::IdealVariable(IdealKit &k) {
   k.declare(this);
@@ -351,9 +337,7 @@
 Node* IdealKit::memory(uint alias_idx) {
   MergeMemNode* mem = merged_memory();
   Node* p = mem->memory_at(alias_idx);
-  if (!gvn().is_IterGVN() || !gvn().is_IterGVN()->delay_transform()) {
-    _gvn.set_type(p, Type::MEMORY);  // must be mapped
-  }
+  _gvn.set_type(p, Type::MEMORY);  // must be mapped
   return p;
 }
 
--- a/src/share/vm/opto/idealKit.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/idealKit.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -102,7 +102,6 @@
   Compile * const C;
   PhaseGVN &_gvn;
   GrowableArray<Node*>* _pending_cvstates; // stack of cvstates
-  GrowableArray<Node*>* _delay_transform;  // delay invoking gvn.transform until drain
   Node* _cvstate;                          // current cvstate (control, memory and variables)
   uint _var_ct;                            // number of variables
   bool _delay_all_transforms;              // flag forcing all transforms to be delayed
@@ -121,7 +120,7 @@
   void clear(Node* m);                     // clear a cvstate
   void stop() { clear(_cvstate); }         // clear current cvstate
   Node* delay_transform(Node* n);
-  Node* transform(Node* n);                // gvn.transform or push node on delay list
+  Node* transform(Node* n);                // gvn.transform or skip it
   Node* promote_to_phi(Node* n, Node* reg);// Promote "n" to a phi on region "reg"
   bool was_promoted_to_phi(Node* n, Node* reg) {
     return (n->is_Phi() && n->in(0) == reg);
@@ -146,7 +145,6 @@
   IdealKit(GraphKit* gkit, bool delay_all_transforms = false, bool has_declarations = false);
   ~IdealKit() {
     stop();
-    drain_delay_transform();
   }
   void sync_kit(GraphKit* gkit);
 
@@ -173,7 +171,6 @@
   void bind(Node* lab);
   void goto_(Node* lab, bool bind = false);
   void declarations_done();
-  void drain_delay_transform();
 
   Node* IfTrue(IfNode* iff)  { return transform(new (C) IfTrueNode(iff)); }
   Node* IfFalse(IfNode* iff) { return transform(new (C) IfFalseNode(iff)); }
@@ -198,7 +195,11 @@
   Node* thread()  {  return gvn().transform(new (C) ThreadLocalNode()); }
 
   // Pointers
-  Node* AddP(Node *base, Node *ptr, Node *off) { return transform(new (C) AddPNode(base, ptr, off)); }
+
+  // Raw address should be transformed regardless 'delay_transform' flag
+  // to produce canonical form CastX2P(offset).
+  Node* AddP(Node *base, Node *ptr, Node *off) { return _gvn.transform(new (C) AddPNode(base, ptr, off)); }
+
   Node* CmpP(Node* l, Node* r) { return transform(new (C) CmpPNode(l, r)); }
 #ifdef _LP64
   Node* XorX(Node* l, Node* r) { return transform(new (C) XorLNode(l, r)); }
@@ -208,8 +209,6 @@
   Node* URShiftX(Node* l, Node* r) { return transform(new (C) URShiftXNode(l, r)); }
   Node* ConX(jint k) { return (Node*)gvn().MakeConX(k); }
   Node* CastPX(Node* ctl, Node* p) { return transform(new (C) CastP2XNode(ctl, p)); }
-  // Add a fixed offset to a pointer
-  Node* basic_plus_adr(Node* base, Node* ptr, intptr_t offset);
 
   // Memory operations
 
--- a/src/share/vm/opto/ifg.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/ifg.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -37,8 +37,6 @@
 #include "opto/memnode.hpp"
 #include "opto/opcodes.hpp"
 
-#define EXACT_PRESSURE 1
-
 //=============================================================================
 //------------------------------IFG--------------------------------------------
 PhaseIFG::PhaseIFG( Arena *arena ) : Phase(Interference_Graph), _arena(arena) {
@@ -445,23 +443,15 @@
       pressure[1] -= lrg->reg_pressure();
       if( pressure[1] == (uint)FLOATPRESSURE ) {
         hrp_index[1] = where;
-#ifdef EXACT_PRESSURE
-      if( pressure[1] > b->_freg_pressure )
-        b->_freg_pressure = pressure[1]+1;
-#else
-        b->_freg_pressure = (uint)FLOATPRESSURE+1;
-#endif
+        if( pressure[1] > b->_freg_pressure )
+          b->_freg_pressure = pressure[1]+1;
       }
     } else if( lrg->mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) {
       pressure[0] -= lrg->reg_pressure();
       if( pressure[0] == (uint)INTPRESSURE   ) {
         hrp_index[0] = where;
-#ifdef EXACT_PRESSURE
-      if( pressure[0] > b->_reg_pressure )
-        b->_reg_pressure = pressure[0]+1;
-#else
-        b->_reg_pressure = (uint)INTPRESSURE+1;
-#endif
+        if( pressure[0] > b->_reg_pressure )
+          b->_reg_pressure = pressure[0]+1;
       }
     }
   }
@@ -526,17 +516,13 @@
       if (lrg.mask().is_UP() && lrg.mask_size()) {
         if (lrg._is_float || lrg._is_vector) {   // Count float pressure
           pressure[1] += lrg.reg_pressure();
-#ifdef EXACT_PRESSURE
           if( pressure[1] > b->_freg_pressure )
             b->_freg_pressure = pressure[1];
-#endif
           // Count int pressure, but do not count the SP, flags
         } else if( lrgs(lidx).mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) {
           pressure[0] += lrg.reg_pressure();
-#ifdef EXACT_PRESSURE
           if( pressure[0] > b->_reg_pressure )
             b->_reg_pressure = pressure[0];
-#endif
         }
       }
     }
@@ -589,30 +575,20 @@
             RegMask itmp = lrgs(r).mask();
             itmp.AND(*Matcher::idealreg2regmask[Op_RegI]);
             int iregs = itmp.Size();
-#ifdef EXACT_PRESSURE
             if( pressure[0]+iregs > b->_reg_pressure )
               b->_reg_pressure = pressure[0]+iregs;
-#endif
             if( pressure[0]       <= (uint)INTPRESSURE &&
                 pressure[0]+iregs >  (uint)INTPRESSURE ) {
-#ifndef EXACT_PRESSURE
-              b->_reg_pressure = (uint)INTPRESSURE+1;
-#endif
               hrp_index[0] = j-1;
             }
             // Count the float-only registers
             RegMask ftmp = lrgs(r).mask();
             ftmp.AND(*Matcher::idealreg2regmask[Op_RegD]);
             int fregs = ftmp.Size();
-#ifdef EXACT_PRESSURE
             if( pressure[1]+fregs > b->_freg_pressure )
               b->_freg_pressure = pressure[1]+fregs;
-#endif
             if( pressure[1]       <= (uint)FLOATPRESSURE &&
                 pressure[1]+fregs >  (uint)FLOATPRESSURE ) {
-#ifndef EXACT_PRESSURE
-              b->_freg_pressure = (uint)FLOATPRESSURE+1;
-#endif
               hrp_index[1] = j-1;
             }
           }
@@ -769,16 +745,12 @@
             if (lrg.mask().is_UP() && lrg.mask_size()) {
               if (lrg._is_float || lrg._is_vector) {
                 pressure[1] += lrg.reg_pressure();
-#ifdef EXACT_PRESSURE
                 if( pressure[1] > b->_freg_pressure )
                   b->_freg_pressure = pressure[1];
-#endif
               } else if( lrg.mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) {
                 pressure[0] += lrg.reg_pressure();
-#ifdef EXACT_PRESSURE
                 if( pressure[0] > b->_reg_pressure )
                   b->_reg_pressure = pressure[0];
-#endif
               }
             }
             assert( pressure[0] == count_int_pressure  (&liveout), "" );
@@ -794,21 +766,13 @@
     // the whole block is high pressure.
     if( pressure[0] > (uint)INTPRESSURE   ) {
       hrp_index[0] = 0;
-#ifdef EXACT_PRESSURE
       if( pressure[0] > b->_reg_pressure )
         b->_reg_pressure = pressure[0];
-#else
-      b->_reg_pressure = (uint)INTPRESSURE+1;
-#endif
     }
     if( pressure[1] > (uint)FLOATPRESSURE ) {
       hrp_index[1] = 0;
-#ifdef EXACT_PRESSURE
       if( pressure[1] > b->_freg_pressure )
         b->_freg_pressure = pressure[1];
-#else
-      b->_freg_pressure = (uint)FLOATPRESSURE+1;
-#endif
     }
 
     // Compute high pressure indice; avoid landing in the middle of projnodes
--- a/src/share/vm/opto/lcm.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/lcm.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -421,6 +421,7 @@
   uint latency = 0; // Bigger is scheduled first
   uint score   = 0; // Bigger is better
   int idx = -1;     // Index in worklist
+  int cand_cnt = 0; // Candidate count
 
   for( uint i=0; i<cnt; i++ ) { // Inspect entire worklist
     // Order in worklist is used to break ties.
@@ -503,11 +504,14 @@
     uint n_score   = n->req();   // Many inputs get high score to break ties
 
     // Keep best latency found
-    if( choice < n_choice ||
-        ( choice == n_choice &&
-          ( latency < n_latency ||
-            ( latency == n_latency &&
-              ( score < n_score ))))) {
+    cand_cnt++;
+    if (choice < n_choice ||
+        (choice == n_choice &&
+         ((StressLCM && Compile::randomized_select(cand_cnt)) ||
+          (!StressLCM &&
+           (latency < n_latency ||
+            (latency == n_latency &&
+             (score < n_score))))))) {
       choice  = n_choice;
       latency = n_latency;
       score   = n_score;
--- a/src/share/vm/opto/library_call.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/library_call.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -231,7 +231,6 @@
   void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
   bool inline_native_clone(bool is_virtual);
   bool inline_native_Reflection_getCallerClass();
-  bool is_method_invoke_or_aux_frame(JVMState* jvms);
   // Helper function for inlining native object hash method
   bool inline_native_hashcode(bool is_virtual, bool is_static);
   bool inline_native_getClass();
@@ -393,7 +392,7 @@
   case vmIntrinsics::_getCallerClass:
     if (!UseNewReflection)  return NULL;
     if (!InlineReflectionGetCallerClass)  return NULL;
-    if (!JDK_Version::is_gte_jdk14x_version())  return NULL;
+    if (SystemDictionary::reflect_CallerSensitive_klass() == NULL)  return NULL;
     break;
 
   case vmIntrinsics::_bitCount_i:
@@ -3872,13 +3871,13 @@
 }
 
 //-----------------inline_native_Reflection_getCallerClass---------------------
-// public static native Class<?> sun.reflect.Reflection.getCallerClass(int realFramesToSkip);
+// public static native Class<?> sun.reflect.Reflection.getCallerClass();
 //
 // In the presence of deep enough inlining, getCallerClass() becomes a no-op.
 //
-// NOTE that this code must perform the same logic as
-// vframeStream::security_get_caller_frame in that it must skip
-// Method.invoke() and auxiliary frames.
+// NOTE: This code must perform the same logic as JVM_GetCallerClass
+// in that it must skip particular security frames and checks for
+// caller sensitive methods.
 bool LibraryCallKit::inline_native_Reflection_getCallerClass() {
 #ifndef PRODUCT
   if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
@@ -3886,35 +3885,6 @@
   }
 #endif
 
-  Node* caller_depth_node = argument(0);
-
-  // The depth value must be a constant in order for the runtime call
-  // to be eliminated.
-  const TypeInt* caller_depth_type = _gvn.type(caller_depth_node)->isa_int();
-  if (caller_depth_type == NULL || !caller_depth_type->is_con()) {
-#ifndef PRODUCT
-    if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
-      tty->print_cr("  Bailing out because caller depth was not a constant");
-    }
-#endif
-    return false;
-  }
-  // Note that the JVM state at this point does not include the
-  // getCallerClass() frame which we are trying to inline. The
-  // semantics of getCallerClass(), however, are that the "first"
-  // frame is the getCallerClass() frame, so we subtract one from the
-  // requested depth before continuing. We don't inline requests of
-  // getCallerClass(0).
-  int caller_depth = caller_depth_type->get_con() - 1;
-  if (caller_depth < 0) {
-#ifndef PRODUCT
-    if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
-      tty->print_cr("  Bailing out because caller depth was %d", caller_depth);
-    }
-#endif
-    return false;
-  }
-
   if (!jvms()->has_method()) {
 #ifndef PRODUCT
     if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
@@ -3923,95 +3893,67 @@
 #endif
     return false;
   }
-  int _depth = jvms()->depth();  // cache call chain depth
 
   // Walk back up the JVM state to find the caller at the required
-  // depth. NOTE that this code must perform the same logic as
-  // vframeStream::security_get_caller_frame in that it must skip
-  // Method.invoke() and auxiliary frames. Note also that depth is
-  // 1-based (1 is the bottom of the inlining).
-  int inlining_depth = _depth;
-  JVMState* caller_jvms = NULL;
-
-  if (inlining_depth > 0) {
-    caller_jvms = jvms();
-    assert(caller_jvms = jvms()->of_depth(inlining_depth), "inlining_depth == our depth");
-    do {
-      // The following if-tests should be performed in this order
-      if (is_method_invoke_or_aux_frame(caller_jvms)) {
-        // Skip a Method.invoke() or auxiliary frame
-      } else if (caller_depth > 0) {
-        // Skip real frame
-        --caller_depth;
-      } else {
-        // We're done: reached desired caller after skipping.
-        break;
+  // depth.
+  JVMState* caller_jvms = jvms();
+
+  // Cf. JVM_GetCallerClass
+  // NOTE: Start the loop at depth 1 because the current JVM state does
+  // not include the Reflection.getCallerClass() frame.
+  for (int n = 1; caller_jvms != NULL; caller_jvms = caller_jvms->caller(), n++) {
+    ciMethod* m = caller_jvms->method();
+    switch (n) {
+    case 0:
+      fatal("current JVM state does not include the Reflection.getCallerClass frame");
+      break;
+    case 1:
+      // Frame 0 and 1 must be caller sensitive (see JVM_GetCallerClass).
+      if (!m->caller_sensitive()) {
+#ifndef PRODUCT
+        if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+          tty->print_cr("  Bailing out: CallerSensitive annotation expected at frame %d", n);
+        }
+#endif
+        return false;  // bail-out; let JVM_GetCallerClass do the work
       }
-      caller_jvms = caller_jvms->caller();
-      --inlining_depth;
-    } while (inlining_depth > 0);
-  }
-
-  if (inlining_depth == 0) {
+      break;
+    default:
+      if (!m->is_ignored_by_security_stack_walk()) {
+        // We have reached the desired frame; return the holder class.
+        // Acquire method holder as java.lang.Class and push as constant.
+        ciInstanceKlass* caller_klass = caller_jvms->method()->holder();
+        ciInstance* caller_mirror = caller_klass->java_mirror();
+        set_result(makecon(TypeInstPtr::make(caller_mirror)));
+
 #ifndef PRODUCT
-    if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
-      tty->print_cr("  Bailing out because caller depth (%d) exceeded inlining depth (%d)", caller_depth_type->get_con(), _depth);
-      tty->print_cr("  JVM state at this point:");
-      for (int i = _depth; i >= 1; i--) {
-        ciMethod* m = jvms()->of_depth(i)->method();
-        tty->print_cr("   %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8());
-      }
-    }
+        if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+          tty->print_cr("  Succeeded: caller = %d) %s.%s, JVMS depth = %d", n, caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), jvms()->depth());
+          tty->print_cr("  JVM state at this point:");
+          for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) {
+            ciMethod* m = jvms()->of_depth(i)->method();
+            tty->print_cr("   %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8());
+          }
+        }
 #endif
-    return false; // Reached end of inlining
+        return true;
+      }
+      break;
+    }
   }
 
-  // Acquire method holder as java.lang.Class
-  ciInstanceKlass* caller_klass  = caller_jvms->method()->holder();
-  ciInstance*      caller_mirror = caller_klass->java_mirror();
-
-  // Push this as a constant
-  set_result(makecon(TypeInstPtr::make(caller_mirror)));
-
 #ifndef PRODUCT
   if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
-    tty->print_cr("  Succeeded: caller = %s.%s, caller depth = %d, depth = %d", caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), caller_depth_type->get_con(), _depth);
+    tty->print_cr("  Bailing out because caller depth exceeded inlining depth = %d", jvms()->depth());
     tty->print_cr("  JVM state at this point:");
-    for (int i = _depth; i >= 1; i--) {
+    for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) {
       ciMethod* m = jvms()->of_depth(i)->method();
-      tty->print_cr("   %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8());
+      tty->print_cr("   %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8());
     }
   }
 #endif
-  return true;
-}
-
-// Helper routine for above
-bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) {
-  ciMethod* method = jvms->method();
-
-  // Is this the Method.invoke method itself?
-  if (method->intrinsic_id() == vmIntrinsics::_invoke)
-    return true;
-
-  // Is this a helper, defined somewhere underneath MethodAccessorImpl.
-  ciKlass* k = method->holder();
-  if (k->is_instance_klass()) {
-    ciInstanceKlass* ik = k->as_instance_klass();
-    for (; ik != NULL; ik = ik->super()) {
-      if (ik->name() == ciSymbol::sun_reflect_MethodAccessorImpl() &&
-          ik == env()->find_system_klass(ik->name())) {
-        return true;
-      }
-    }
-  }
-  else if (method->is_method_handle_intrinsic() ||
-           method->is_compiled_lambda_form()) {
-    // This is an internal adapter frame from the MethodHandleCompiler -- skip it
-    return true;
-  }
-
-  return false;
+
+  return false;  // bail-out; let JVM_GetCallerClass do the work
 }
 
 bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) {
--- a/src/share/vm/opto/live.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/live.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -33,11 +33,35 @@
 #include "opto/regmask.hpp"
 
 class Block;
-class LRG_List;
 class PhaseCFG;
 class VectorSet;
 class IndexSet;
 
+//------------------------------LRG_List---------------------------------------
+// Map Node indices to Live RanGe indices.
+// Array lookup in the optimized case.
+class LRG_List : public ResourceObj {
+  friend class VMStructs;
+  uint _cnt, _max;
+  uint* _lidxs;
+  ReallocMark _nesting;         // assertion check for reallocations
+public:
+  LRG_List( uint max );
+
+  uint lookup( uint nidx ) const {
+    return _lidxs[nidx];
+  }
+  uint operator[] (uint nidx) const { return lookup(nidx); }
+
+  void map( uint nidx, uint lidx ) {
+    assert( nidx < _cnt, "oob" );
+    _lidxs[nidx] = lidx;
+  }
+  void extend( uint nidx, uint lidx );
+
+  uint Size() const { return _cnt; }
+};
+
 //------------------------------PhaseLive--------------------------------------
 // Compute live-in/live-out
 class PhaseLive : public Phase {
--- a/src/share/vm/opto/loopTransform.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/loopTransform.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -888,6 +888,7 @@
   CountedLoopNode *main_head = loop->_head->as_CountedLoop();
   assert( main_head->is_normal_loop(), "" );
   CountedLoopEndNode *main_end = main_head->loopexit();
+  guarantee(main_end != NULL, "no loop exit node");
   assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
   uint dd_main_head = dom_depth(main_head);
   uint max = main_head->outcnt();
@@ -2554,13 +2555,16 @@
   ok.set(store->_idx);
   ok.set(store->in(MemNode::Memory)->_idx);
 
+  CountedLoopEndNode* loop_exit = head->loopexit();
+  guarantee(loop_exit != NULL, "no loop exit node");
+
   // Loop structure is ok
   ok.set(head->_idx);
-  ok.set(head->loopexit()->_idx);
+  ok.set(loop_exit->_idx);
   ok.set(head->phi()->_idx);
   ok.set(head->incr()->_idx);
-  ok.set(head->loopexit()->cmp_node()->_idx);
-  ok.set(head->loopexit()->in(1)->_idx);
+  ok.set(loop_exit->cmp_node()->_idx);
+  ok.set(loop_exit->in(1)->_idx);
 
   // Address elements are ok
   if (con)   ok.set(con->_idx);
@@ -2572,7 +2576,7 @@
     if (n->outcnt() == 0) continue; // Ignore dead
     if (ok.test(n->_idx)) continue;
     // Backedge projection is ok
-    if (n->is_IfTrue() && n->in(0) == head->loopexit()) continue;
+    if (n->is_IfTrue() && n->in(0) == loop_exit) continue;
     if (!n->is_AddP()) {
       msg = "unhandled node";
       msg_node = n;
@@ -2585,7 +2589,7 @@
     Node* n = lpt->_body.at(i);
     // These values can be replaced with other nodes if they are used
     // outside the loop.
-    if (n == store || n == head->loopexit() || n == head->incr() || n == store->in(MemNode::Memory)) continue;
+    if (n == store || n == loop_exit || n == head->incr() || n == store->in(MemNode::Memory)) continue;
     for (SimpleDUIterator iter(n); iter.has_next(); iter.next()) {
       Node* use = iter.get();
       if (!lpt->_body.contains(use)) {
--- a/src/share/vm/opto/loopnode.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/loopnode.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -2251,6 +2251,11 @@
     return;
   }
 
+  // clear out the dead code after build_loop_late
+  while (_deadlist.size()) {
+    _igvn.remove_globally_dead_node(_deadlist.pop());
+  }
+
   if (stop_early) {
     assert(do_expensive_nodes, "why are we here?");
     if (process_expensive_nodes()) {
@@ -2260,9 +2265,7 @@
       // nodes again.
       C->set_major_progress();
     }
-
     _igvn.optimize();
-
     return;
   }
 
@@ -2273,11 +2276,6 @@
     eliminate_useless_predicates();
   }
 
-  // clear out the dead code
-  while(_deadlist.size()) {
-    _igvn.remove_globally_dead_node(_deadlist.pop());
-  }
-
 #ifndef PRODUCT
   C->verify_graph_edges();
   if (_verify_me) {             // Nested verify pass?
--- a/src/share/vm/opto/loopnode.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/loopnode.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -603,7 +603,10 @@
   }
 
 public:
-  bool has_node( Node* n ) const { return _nodes[n->_idx] != NULL; }
+  bool has_node( Node* n ) const {
+    guarantee(n != NULL, "No Node.");
+    return _nodes[n->_idx] != NULL;
+  }
   // check if transform created new nodes that need _ctrl recorded
   Node *get_late_ctrl( Node *n, Node *early );
   Node *get_early_ctrl( Node *n );
@@ -737,7 +740,8 @@
     return n;
   }
   uint dom_depth(Node* d) const {
-    assert(d->_idx < _idom_size, "");
+    guarantee(d != NULL, "Null dominator info.");
+    guarantee(d->_idx < _idom_size, "");
     return _dom_depth[d->_idx];
   }
   void set_idom(Node* d, Node* n, uint dom_depth);
--- a/src/share/vm/opto/loopopts.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/loopopts.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -232,7 +232,11 @@
   // Loop predicates may have depending checks which should not
   // be skipped. For example, range check predicate has two checks
   // for lower and upper bounds.
-  ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp->as_Proj()->_con)->as_Proj();
+  if (dp == NULL)
+    return;
+
+  ProjNode* dp_proj  = dp->as_Proj();
+  ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj();
   if (exclude_loop_predicate &&
       is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate))
     return; // Let IGVN transformation change control dependence.
@@ -866,8 +870,11 @@
 
     // Now split the bool up thru the phi
     Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
+    guarantee(bolphi != NULL, "null boolean phi node");
+
     _igvn.replace_node( bol, bolphi );
     assert( iff->in(1) == bolphi, "" );
+
     if( bolphi->Value(&_igvn)->singleton() )
       return;
 
@@ -1628,6 +1635,7 @@
 //------------------------------ short_circuit_if -------------------------------------
 // Force the iff control output to be the live_proj
 Node* PhaseIdealLoop::short_circuit_if(IfNode* iff, ProjNode* live_proj) {
+  guarantee(live_proj != NULL, "null projection");
   int proj_con = live_proj->_con;
   assert(proj_con == 0 || proj_con == 1, "false or true projection");
   Node *con = _igvn.intcon(proj_con);
@@ -1686,6 +1694,7 @@
   set_idom(proj, new_if, ddepth);
 
   ProjNode* new_exit = proj_clone(other_proj, new_if)->as_Proj();
+  guarantee(new_exit != NULL, "null exit node");
   register_node(new_exit, get_loop(other_proj), new_if, ddepth);
 
   return new_exit;
@@ -1793,7 +1802,10 @@
   int stride = stride_of_possible_iv(if_cmpu);
   if (stride == 0) return NULL;
 
-  ProjNode* lp_continue = stay_in_loop(if_cmpu, loop)->as_Proj();
+  Node* lp_proj = stay_in_loop(if_cmpu, loop);
+  guarantee(lp_proj != NULL, "null loop node");
+
+  ProjNode* lp_continue = lp_proj->as_Proj();
   ProjNode* lp_exit     = if_cmpu->proj_out(!lp_continue->is_IfTrue())->as_Proj();
 
   Node* limit = NULL;
@@ -1805,6 +1817,7 @@
   }
   // Create a new region on the exit path
   RegionNode* reg = insert_region_before_proj(lp_exit);
+  guarantee(reg != NULL, "null region node");
 
   // Clone the if-cmpu-true-false using a signed compare
   BoolTest::mask rel_i = stride > 0 ? bol->_test._test : BoolTest::ge;
--- a/src/share/vm/opto/macro.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/macro.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1101,12 +1101,6 @@
   Node* klass_node        = alloc->in(AllocateNode::KlassNode);
   Node* initial_slow_test = alloc->in(AllocateNode::InitialTest);
 
-  Node* storestore = alloc->storestore();
-  if (storestore != NULL) {
-    // Break this link that is no longer useful and confuses register allocation
-    storestore->set_req(MemBarNode::Precedent, top());
-  }
-
   assert(ctrl != NULL, "must have control");
   // We need a Region and corresponding Phi's to merge the slow-path and fast-path results.
   // they will not be used if "always_slow" is set
@@ -1324,7 +1318,7 @@
         // No InitializeNode or no stores captured by zeroing
         // elimination. Simply add the MemBarStoreStore after object
         // initialization.
-        MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot, fast_oop_rawmem);
+        MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot);
         transform_later(mb);
 
         mb->init_req(TypeFunc::Memory, fast_oop_rawmem);
--- a/src/share/vm/opto/memnode.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/memnode.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -238,7 +238,7 @@
     return this;
   ctl = in(MemNode::Control);
   // Don't bother trying to transform a dead node
-  if( ctl && ctl->is_top() )  return NodeSentinel;
+  if (ctl && ctl->is_top())  return NodeSentinel;
 
   PhaseIterGVN *igvn = phase->is_IterGVN();
   // Wait if control on the worklist.
@@ -262,8 +262,8 @@
   }
   // Ignore if memory is dead, or self-loop
   Node *mem = in(MemNode::Memory);
-  if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL
-  assert( mem != this, "dead loop in MemNode::Ideal" );
+  if (phase->type( mem ) == Type::TOP) return NodeSentinel; // caller will return NULL
+  assert(mem != this, "dead loop in MemNode::Ideal");
 
   if (can_reshape && igvn != NULL && igvn->_worklist.member(mem)) {
     // This memory slice may be dead.
@@ -273,12 +273,12 @@
   }
 
   Node *address = in(MemNode::Address);
-  const Type *t_adr = phase->type( address );
-  if( t_adr == Type::TOP )              return NodeSentinel; // caller will return NULL
-
-  if( can_reshape && igvn != NULL &&
+  const Type *t_adr = phase->type(address);
+  if (t_adr == Type::TOP)              return NodeSentinel; // caller will return NULL
+
+  if (can_reshape && igvn != NULL &&
       (igvn->_worklist.member(address) ||
-       igvn->_worklist.size() > 0 && (phase->type(address) != adr_type())) ) {
+       igvn->_worklist.size() > 0 && (t_adr != adr_type())) ) {
     // The address's base and type may change when the address is processed.
     // Delay this mem node transformation until the address is processed.
     phase->is_IterGVN()->_worklist.push(this);
@@ -288,7 +288,7 @@
   // Do NOT remove or optimize the next lines: ensure a new alias index
   // is allocated for an oop pointer type before Escape Analysis.
   // Note: C++ will not remove it since the call has side effect.
-  if ( t_adr->isa_oopptr() ) {
+  if (t_adr->isa_oopptr()) {
     int alias_idx = phase->C->get_alias_index(t_adr->is_ptr());
   }
 
@@ -296,6 +296,26 @@
   Node* base = NULL;
   if (address->is_AddP())
     base = address->in(AddPNode::Base);
+  if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) &&
+      !t_adr->isa_rawptr()) {
+    // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true.
+    Compile* C = phase->C;
+    tty->cr();
+    tty->print_cr("===== NULL+offs not RAW address =====");
+    if (C->is_dead_node(this->_idx))    tty->print_cr("'this' is dead");
+    if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead");
+    if (C->is_dead_node(mem->_idx))     tty->print_cr("'mem' is dead");
+    if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead");
+    if (C->is_dead_node(base->_idx))    tty->print_cr("'base' is dead");
+    tty->cr();
+    base->dump(1);
+    tty->cr();
+    this->dump(2);
+    tty->print("this->adr_type():     "); adr_type()->dump(); tty->cr();
+    tty->print("phase->type(address): "); t_adr->dump(); tty->cr();
+    tty->print("phase->type(base):    "); phase->type(address)->dump(); tty->cr();
+    tty->cr();
+  }
   assert(base == NULL || t_adr->isa_rawptr() ||
         !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?");
 #endif
--- a/src/share/vm/opto/output.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/output.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -449,6 +449,17 @@
       int max_loop_pad = nb->code_alignment()-relocInfo::addr_unit();
       if (max_loop_pad > 0) {
         assert(is_power_of_2(max_loop_pad+relocInfo::addr_unit()), "");
+        // Adjust last_call_adr and/or last_avoid_back_to_back_adr.
+        // If either is the last instruction in this block, bump by
+        // max_loop_pad in lock-step with blk_size, so sizing
+        // calculations in subsequent blocks still can conservatively
+        // detect that it may the last instruction in this block.
+        if (last_call_adr == blk_starts[i]+blk_size) {
+          last_call_adr += max_loop_pad;
+        }
+        if (last_avoid_back_to_back_adr == blk_starts[i]+blk_size) {
+          last_avoid_back_to_back_adr += max_loop_pad;
+        }
         blk_size += max_loop_pad;
       }
     }
@@ -1196,8 +1207,6 @@
   int last_call_offset = -1;
   int last_avoid_back_to_back_offset = -1;
 #ifdef ASSERT
-  int block_alignment_padding = 0;
-
   uint* jmp_target = NEW_RESOURCE_ARRAY(uint,nblocks);
   uint* jmp_offset = NEW_RESOURCE_ARRAY(uint,nblocks);
   uint* jmp_size   = NEW_RESOURCE_ARRAY(uint,nblocks);
@@ -1231,8 +1240,6 @@
   Node *delay_slot = NULL;
 
   for (uint i=0; i < nblocks; i++) {
-    guarantee(blk_starts[i] >= (uint)cb->insts_size(),"should not increase size");
-
     Block *b = _cfg->_blocks[i];
 
     Node *head = b->head();
@@ -1253,14 +1260,6 @@
     jmp_offset[i] = 0;
     jmp_size[i]   = 0;
     jmp_rule[i]   = 0;
-
-    // Maximum alignment padding for loop block was used
-    // during first round of branches shortening, as result
-    // padding for nodes (sfpt after call) was not added.
-    // Take this into account for block's size change check
-    // and allow increase block's size by the difference
-    // of maximum and actual alignment paddings.
-    int orig_blk_size = blk_starts[i+1] - blk_starts[i] + block_alignment_padding;
 #endif
     int blk_offset = current_offset;
 
@@ -1560,8 +1559,6 @@
       }
 
     } // End for all instructions in block
-    assert((uint)blk_offset <= blk_starts[i], "shouldn't increase distance");
-    blk_starts[i] = blk_offset;
 
     // If the next block is the top of a loop, pad this block out to align
     // the loop top a little. Helps prevent pipe stalls at loop back branches.
@@ -1575,16 +1572,13 @@
         nop->emit(*cb, _regalloc);
         current_offset = cb->insts_size();
       }
-#ifdef ASSERT
-      int max_loop_pad = nb->code_alignment()-relocInfo::addr_unit();
-      block_alignment_padding = (max_loop_pad - padding);
-      assert(block_alignment_padding >= 0, "sanity");
-#endif
     }
     // Verify that the distance for generated before forward
     // short branches is still valid.
-    assert(orig_blk_size >= (current_offset - blk_offset), "shouldn't increase block size");
-
+    guarantee((int)(blk_starts[i+1] - blk_starts[i]) >= (current_offset - blk_offset), "shouldn't increase block size");
+
+    // Save new block start offset
+    blk_starts[i] = blk_offset;
   } // End of for all blocks
   blk_starts[nblocks] = current_offset;
 
@@ -2521,6 +2515,7 @@
     // Schedule the remaining instructions in the block
     while ( _available.size() > 0 ) {
       Node *n = ChooseNodeToBundle();
+      guarantee(n != NULL, "no nodes available");
       AddNodeToBundle(n,bb);
     }
 
--- a/src/share/vm/opto/parse2.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/parse2.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -104,7 +104,8 @@
     if (C->log() != NULL)   C->log()->elem("observe that='!need_range_check'");
   }
 
-  if (!arytype->klass()->is_loaded()) {
+  ciKlass * arytype_klass = arytype->klass();
+  if ((arytype_klass != NULL) && (!arytype_klass->is_loaded())) {
     // Only fails for some -Xcomp runs
     // The class is unloaded.  We have to run this bytecode in the interpreter.
     uncommon_trap(Deoptimization::Reason_unloaded,
@@ -1385,6 +1386,7 @@
   if (TraceOptoParse) {
     tty->print(" @");
     dump_bci(bci());
+    tty->cr();
   }
 #endif
 
--- a/src/share/vm/opto/phaseX.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/phaseX.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1166,31 +1166,30 @@
     if (progress_state == PROCESS_INPUTS) {
       // After following inputs, continue to outputs
       _stack.set_index(PROCESS_OUTPUTS);
-      // Remove from iterative worklist
-      _worklist.remove(dead);
       if (!dead->is_Con()) { // Don't kill cons but uses
         bool recurse = false;
         // Remove from hash table
         _table.hash_delete( dead );
         // Smash all inputs to 'dead', isolating him completely
-        for( uint i = 0; i < dead->req(); i++ ) {
+        for (uint i = 0; i < dead->req(); i++) {
           Node *in = dead->in(i);
-          if( in ) {                 // Points to something?
-            dead->set_req(i,NULL);  // Kill the edge
-            if (in->outcnt() == 0 && in != C->top()) {// Made input go dead?
+          if (in != NULL && in != C->top()) {  // Points to something?
+            int nrep = dead->replace_edge(in, NULL);  // Kill edges
+            assert((nrep > 0), "sanity");
+            if (in->outcnt() == 0) { // Made input go dead?
               _stack.push(in, PROCESS_INPUTS); // Recursively remove
               recurse = true;
             } else if (in->outcnt() == 1 &&
                        in->has_special_unique_user()) {
               _worklist.push(in->unique_out());
             } else if (in->outcnt() <= 2 && dead->is_Phi()) {
-              if( in->Opcode() == Op_Region )
+              if (in->Opcode() == Op_Region) {
                 _worklist.push(in);
-              else if( in->is_Store() ) {
+              } else if (in->is_Store()) {
                 DUIterator_Fast imax, i = in->fast_outs(imax);
                 _worklist.push(in->fast_out(i));
                 i++;
-                if(in->outcnt() == 2) {
+                if (in->outcnt() == 2) {
                   _worklist.push(in->fast_out(i));
                   i++;
                 }
@@ -1209,38 +1208,42 @@
                 }
               }
             }
-          }
-        }
-        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 (in != NULL && in != C->top())
+        } // for (uint i = 0; i < dead->req(); i++)
         if (recurse) {
           continue;
         }
-      }
-      // Constant node that has no out-edges and has only one in-edge from
-      // root is usually dead. However, sometimes reshaping walk makes
-      // it reachable by adding use edges. So, we will NOT count Con nodes
-      // as dead to be conservative about the dead node count at any
-      // given time.
-    }
+      } // if (!dead->is_Con())
+    } // if (progress_state == PROCESS_INPUTS)
 
     // Aggressively kill globally dead uses
     // (Rather than pushing all the outs at once, we push one at a time,
     // plus the parent to resume later, because of the indefinite number
     // of edge deletions per loop trip.)
     if (dead->outcnt() > 0) {
-      // Recursively remove
+      // Recursively remove output edges
       _stack.push(dead->raw_out(0), PROCESS_INPUTS);
     } else {
+      // Finished disconnecting all input and output edges.
       _stack.pop();
+      // Remove dead node from iterative worklist
+      _worklist.remove(dead);
+      // Constant node that has no out-edges and has only one in-edge from
+      // root is usually dead. However, sometimes reshaping walk makes
+      // it reachable by adding use edges. So, we will NOT count Con nodes
+      // as dead to be conservative about the dead node count at any
+      // given time.
+      if (!dead->is_Con()) {
+        C->record_dead_node(dead->_idx);
+      }
+      if (dead->is_macro()) {
+        C->remove_macro_node(dead);
+      }
+      if (dead->is_expensive()) {
+        C->remove_expensive_node(dead);
+      }
     }
-  }
+  } // while (_stack.is_nonempty())
 }
 
 //------------------------------subsume_node-----------------------------------
--- a/src/share/vm/opto/subnode.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/subnode.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1078,16 +1078,6 @@
   return (_test._test == b->_test._test);
 }
 
-//------------------------------clone_cmp--------------------------------------
-// Clone a compare/bool tree
-static Node *clone_cmp( Node *cmp, Node *cmp1, Node *cmp2, PhaseGVN *gvn, BoolTest::mask test ) {
-  Node *ncmp = cmp->clone();
-  ncmp->set_req(1,cmp1);
-  ncmp->set_req(2,cmp2);
-  ncmp = gvn->transform( ncmp );
-  return new (gvn->C) BoolNode( ncmp, test );
-}
-
 //-------------------------------make_predicate--------------------------------
 Node* BoolNode::make_predicate(Node* test_value, PhaseGVN* phase) {
   if (test_value->is_Con())   return test_value;
--- a/src/share/vm/opto/type.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/opto/type.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -4193,6 +4193,7 @@
   bool    xk = klass_is_exact();
   //return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0);
   const TypeOopPtr* toop = TypeOopPtr::make_from_klass_raw(k);
+  guarantee(toop != NULL, "need type for given klass");
   toop = toop->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr();
   return toop->cast_to_exactness(xk)->is_oopptr();
 }
--- a/src/share/vm/prims/jni.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jni.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
  * Copyright (c) 2012 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -95,7 +95,7 @@
 # include "os_bsd.inline.hpp"
 #endif
 
-static jint CurrentVersion = JNI_VERSION_1_6;
+static jint CurrentVersion = JNI_VERSION_1_8;
 
 
 // The DT_RETURN_MARK macros create a scoped object to fire the dtrace
@@ -1292,32 +1292,6 @@
   JNI_NONVIRTUAL
 };
 
-static methodHandle jni_resolve_interface_call(Handle recv, methodHandle method, TRAPS) {
-  assert(!method.is_null() , "method should not be null");
-
-  KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
-  if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
-  KlassHandle spec_klass (THREAD, method->method_holder());
-  Symbol*  name  = method->name();
-  Symbol*  signature  = method->signature();
-  CallInfo info;
-  LinkResolver::resolve_interface_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
-  return info.selected_method();
-}
-
-static methodHandle jni_resolve_virtual_call(Handle recv, methodHandle method, TRAPS) {
-  assert(!method.is_null() , "method should not be null");
-
-  KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
-  if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
-  KlassHandle spec_klass (THREAD, method->method_holder());
-  Symbol*  name  = method->name();
-  Symbol*  signature  = method->signature();
-  CallInfo info;
-  LinkResolver::resolve_virtual_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
-  return info.selected_method();
-}
-
 
 
 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
@@ -5056,6 +5030,7 @@
 void execute_internal_vm_tests() {
   if (ExecuteInternalVMTests) {
     tty->print_cr("Running internal VM tests");
+    run_unit_test(GlobalDefinitions::test_globals());
     run_unit_test(arrayOopDesc::test_max_array_length());
     run_unit_test(CollectedHeap::test_is_in());
     run_unit_test(QuickSort::test_quick_sort());
--- a/src/share/vm/prims/jni.h	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jni.h	Mon Apr 15 08:51:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, 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
@@ -1951,6 +1951,7 @@
 #define JNI_VERSION_1_2 0x00010002
 #define JNI_VERSION_1_4 0x00010004
 #define JNI_VERSION_1_6 0x00010006
+#define JNI_VERSION_1_8 0x00010008
 
 #ifdef __cplusplus
 } /* extern "C" */
--- a/src/share/vm/prims/jniCheck.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jniCheck.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -33,7 +33,7 @@
   // within IN_VM macro), one to be called when in NATIVE state.
 
   // When in VM state:
-  static void ReportJNIFatalError(JavaThread* thr, const char *msg) {
+  static inline void ReportJNIFatalError(JavaThread* thr, const char *msg) {
     tty->print_cr("FATAL ERROR in native method: %s", msg);
     thr->print_stack();
     os::abort(true);
--- a/src/share/vm/prims/jvm.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvm.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -30,6 +30,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
+#include "interpreter/bytecode.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/fieldStreams.hpp"
@@ -667,8 +668,51 @@
 
 JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
   JVMWrapper("JVM_GetCallerClass");
-  Klass* k = thread->security_get_caller_class(depth);
-  return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
+
+  // Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation.
+  if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) {
+    Klass* k = thread->security_get_caller_class(depth);
+    return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
+  } else {
+    // Basic handshaking with Java_sun_reflect_Reflection_getCallerClass
+    assert(depth == -1, "wrong handshake depth");
+  }
+
+  // Getting the class of the caller frame.
+  //
+  // The call stack at this point looks something like this:
+  //
+  // [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
+  // [1] [ @CallerSensitive API.method                                   ]
+  // [.] [ (skipped intermediate frames)                                 ]
+  // [n] [ caller                                                        ]
+  vframeStream vfst(thread);
+  // Cf. LibraryCallKit::inline_native_Reflection_getCallerClass
+  for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) {
+    Method* m = vfst.method();
+    assert(m != NULL, "sanity");
+    switch (n) {
+    case 0:
+      // This must only be called from Reflection.getCallerClass
+      if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) {
+        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass");
+      }
+      // fall-through
+    case 1:
+      // Frame 0 and 1 must be caller sensitive.
+      if (!m->caller_sensitive()) {
+        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d", n));
+      }
+      break;
+    default:
+      if (!m->is_ignored_by_security_stack_walk()) {
+        // We have reached the desired frame; return the holder class.
+        return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror());
+      }
+      break;
+    }
+  }
+  return NULL;
 JVM_END
 
 
@@ -1459,7 +1503,7 @@
 JVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls))
   assert (cls != NULL, "illegal class");
   JVMWrapper("JVM_GetClassAnnotations");
-  ResourceMark rm(THREAD);
+
   // Return null for arrays and primitives
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
@@ -1472,20 +1516,15 @@
 JVM_END
 
 
-JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field))
-  assert(field != NULL, "illegal field");
-  JVMWrapper("JVM_GetFieldAnnotations");
-
+static bool jvm_get_field_common(jobject field, fieldDescriptor& fd, TRAPS) {
   // some of this code was adapted from from jni_FromReflectedField
 
-  // field is a handle to a java.lang.reflect.Field object
   oop reflected = JNIHandles::resolve_non_null(field);
   oop mirror    = java_lang_reflect_Field::clazz(reflected);
   Klass* k    = java_lang_Class::as_Klass(mirror);
   int slot      = java_lang_reflect_Field::slot(reflected);
   int modifiers = java_lang_reflect_Field::modifiers(reflected);
 
-  fieldDescriptor fd;
   KlassHandle kh(THREAD, k);
   intptr_t offset = InstanceKlass::cast(kh())->field_offset(slot);
 
@@ -1493,16 +1532,29 @@
     // for static fields we only look in the current class
     if (!InstanceKlass::cast(kh())->find_local_field_from_offset(offset, true, &fd)) {
       assert(false, "cannot find static field");
-      return NULL;  // robustness
+      return false;
     }
   } else {
     // for instance fields we start with the current class and work
     // our way up through the superclass chain
     if (!InstanceKlass::cast(kh())->find_field_from_offset(offset, false, &fd)) {
       assert(false, "cannot find instance field");
-      return NULL;  // robustness
+      return false;
     }
   }
+  return true;
+}
+
+JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field))
+  // field is a handle to a java.lang.reflect.Field object
+  assert(field != NULL, "illegal field");
+  JVMWrapper("JVM_GetFieldAnnotations");
+
+  fieldDescriptor fd;
+  bool gotFd = jvm_get_field_common(field, fd, CHECK_NULL);
+  if (!gotFd) {
+    return NULL;
+  }
 
   return (jbyteArray) JNIHandles::make_local(env, Annotations::make_java_array(fd.annotations(), THREAD));
 JVM_END
@@ -1527,12 +1579,8 @@
   Klass* k = java_lang_Class::as_Klass(mirror);
 
   Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
-  if (m == NULL) {
-    assert(false, "cannot find method");
-    return NULL;  // robustness
-  }
-
-  return m;
+  assert(m != NULL, "cannot find method");
+  return m;  // caller has to deal with NULL in product mode
 }
 
 
@@ -1541,6 +1589,10 @@
 
   // method is a handle to a java.lang.reflect.Method object
   Method* m = jvm_get_method_common(method);
+  if (m == NULL) {
+    return NULL;
+  }
+
   return (jbyteArray) JNIHandles::make_local(env,
     Annotations::make_java_array(m->annotations(), THREAD));
 JVM_END
@@ -1551,6 +1603,10 @@
 
   // method is a handle to a java.lang.reflect.Method object
   Method* m = jvm_get_method_common(method);
+  if (m == NULL) {
+    return NULL;
+  }
+
   return (jbyteArray) JNIHandles::make_local(env,
     Annotations::make_java_array(m->annotation_default(), THREAD));
 JVM_END
@@ -1561,6 +1617,10 @@
 
   // method is a handle to a java.lang.reflect.Method object
   Method* m = jvm_get_method_common(method);
+  if (m == NULL) {
+    return NULL;
+  }
+
   return (jbyteArray) JNIHandles::make_local(env,
     Annotations::make_java_array(m->parameter_annotations(), THREAD));
 JVM_END
@@ -1585,6 +1645,38 @@
   return NULL;
 JVM_END
 
+JVM_ENTRY(jbyteArray, JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method))
+  assert (method != NULL, "illegal method");
+  JVMWrapper("JVM_GetMethodTypeAnnotations");
+
+  // method is a handle to a java.lang.reflect.Method object
+  Method* m = jvm_get_method_common(method);
+  if (m == NULL) {
+    return NULL;
+  }
+
+  AnnotationArray* type_annotations = m->type_annotations();
+  if (type_annotations != NULL) {
+    typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
+    return (jbyteArray) JNIHandles::make_local(env, a);
+  }
+
+  return NULL;
+JVM_END
+
+JVM_ENTRY(jbyteArray, JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field))
+  assert (field != NULL, "illegal field");
+  JVMWrapper("JVM_GetFieldTypeAnnotations");
+
+  fieldDescriptor fd;
+  bool gotFd = jvm_get_field_common(field, fd, CHECK_NULL);
+  if (!gotFd) {
+    return NULL;
+  }
+
+  return (jbyteArray) JNIHandles::make_local(env, Annotations::make_java_array(fd.type_annotations(), THREAD));
+JVM_END
+
 static void bounds_check(constantPoolHandle cp, jint index, TRAPS) {
   if (!cp->is_within_bounds(index)) {
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds");
@@ -1724,7 +1816,7 @@
   int i;
   for (i = 0; i < methods_length; i++) {
     methodHandle method(THREAD, methods->at(i));
-    if (!method->is_initializer()) {
+    if (!method->is_initializer() && !method->is_overpass()) {
       if (!publicOnly || method->is_public()) {
         ++num_methods;
       }
@@ -1738,7 +1830,7 @@
   int out_idx = 0;
   for (i = 0; i < methods_length; i++) {
     methodHandle method(THREAD, methods->at(i));
-    if (!method->is_initializer()) {
+    if (!method->is_initializer() && !method->is_overpass()) {
       if (!publicOnly || method->is_public()) {
         oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL);
         result->obj_at_put(out_idx, m);
@@ -3162,11 +3254,24 @@
   KlassLink* first = NULL;
   KlassLink* last  = NULL;
   int depth = 0;
-
-  for(vframeStream vfst(thread); !vfst.at_end(); vfst.security_get_caller_frame(1)) {
+  vframeStream vfst(thread);
+
+  if (SystemDictionary::reflect_CallerSensitive_klass() != NULL) {
+    // This must only be called from SecurityManager.getClassContext
+    Method* m = vfst.method();
+    if (!(m->method_holder() == SystemDictionary::SecurityManager_klass() &&
+          m->name()          == vmSymbols::getClassContext_name() &&
+          m->signature()     == vmSymbols::void_class_array_signature())) {
+      THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext");
+    }
+  }
+
+  // Collect method holders
+  for (; !vfst.at_end(); vfst.security_next()) {
+    Method* m = vfst.method();
     // Native frames are not returned
-    if (!vfst.method()->is_native()) {
-      Klass* holder = vfst.method()->method_holder();
+    if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) {
+      Klass* holder = m->method_holder();
       assert(holder->is_klass(), "just checking");
       depth++;
       KlassLink* l = new KlassLink(KlassHandle(thread, holder));
--- a/src/share/vm/prims/jvm.h	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvm.h	Mon Apr 15 08:51:19 2013 +0200
@@ -523,6 +523,14 @@
 JNIEXPORT jbyteArray JNICALL
 JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
 
+// field is a handle to a java.lang.reflect.Field object
+JNIEXPORT jbyteArray JNICALL
+JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field);
+
+// method is a handle to a java.lang.reflect.Method object
+JNIEXPORT jbyteArray JNICALL
+JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method);
+
 /*
  * New (JDK 1.4) reflection implementation
  */
--- a/src/share/vm/prims/jvmtiEnter.xsl	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiEnter.xsl	Mon Apr 15 08:51:19 2013 +0200
@@ -773,7 +773,7 @@
 </xsl:text>
     <xsl:apply-templates select=".." mode="traceError">     
       <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param>
-      <xsl:with-param name="comment"> - jthread resolved to NULL - jthread = %0x%x</xsl:with-param>
+      <xsl:with-param name="comment"> - jthread resolved to NULL - jthread = 0x%x</xsl:with-param>
       <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param>
     </xsl:apply-templates>
     <xsl:text>
@@ -782,7 +782,7 @@
 </xsl:text>
     <xsl:apply-templates select=".." mode="traceError">     
       <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param>
-      <xsl:with-param name="comment"> - oop is not a thread - jthread = %0x%x</xsl:with-param>
+      <xsl:with-param name="comment"> - oop is not a thread - jthread = 0x%x</xsl:with-param>
       <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param>
     </xsl:apply-templates>
     <xsl:text>
@@ -794,7 +794,7 @@
       <xsl:with-param name="err">
         <xsl:text>JVMTI_ERROR_THREAD_NOT_ALIVE</xsl:text>
       </xsl:with-param>
-      <xsl:with-param name="comment"> - not a Java thread - jthread = %0x%x</xsl:with-param>
+      <xsl:with-param name="comment"> - not a Java thread - jthread = 0x%x</xsl:with-param>
       <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param>
     </xsl:apply-templates>
     <xsl:text>
@@ -838,7 +838,7 @@
 </xsl:text>
     <xsl:apply-templates select=".." mode="traceError">     
       <xsl:with-param name="err">JVMTI_ERROR_ILLEGAL_ARGUMENT</xsl:with-param>
-      <xsl:with-param name="comment"> - negative depth - jthread = %0x%x</xsl:with-param>
+      <xsl:with-param name="comment"> - negative depth - jthread = 0x%x</xsl:with-param>
       <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param>
     </xsl:apply-templates>
     <xsl:text>
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -997,13 +997,19 @@
       // move our object at this point. However, our owner value is safe
       // since it is either the Lock word on a stack or a JavaThread *.
       owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint);
-      assert(owning_thread != NULL, "sanity check");
-      if (owning_thread != NULL) {  // robustness
+      // Cannot assume (owning_thread != NULL) here because this function
+      // may not have been called at a safepoint and the owning_thread
+      // might not be suspended.
+      if (owning_thread != NULL) {
         // The monitor's owner either has to be the current thread, at safepoint
         // or it has to be suspended. Any of these conditions will prevent both
         // contending and waiting threads from modifying the state of
         // the monitor.
         if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) {
+          // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED
+          // will not make it back to the JVM/TI agent. The error code will
+          // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which
+          // will retry the call via a VM_GetObjectMonitorUsage VM op.
           return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
         }
         HandleMark hm;
--- a/src/share/vm/prims/jvmtiEventController.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiEventController.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -39,7 +39,12 @@
 #include "runtime/vm_operations.hpp"
 
 #ifdef JVMTI_TRACE
-#define EC_TRACE(out) if (JvmtiTrace::trace_event_controller()) { SafeResourceMark rm; tty->print_cr out; } while (0)
+#define EC_TRACE(out) do { \
+  if (JvmtiTrace::trace_event_controller()) { \
+    SafeResourceMark rm; \
+    tty->print_cr out; \
+  } \
+} while (0)
 #else
 #define EC_TRACE(out)
 #endif /*JVMTI_TRACE */
--- a/src/share/vm/prims/jvmtiImpl.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -890,7 +890,7 @@
 
   tty->print("Suspended Threads: [");
   for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
-#if JVMTI_TRACE
+#ifdef JVMTI_TRACE
     const char *name   = JvmtiTrace::safe_get_thread_name(thread);
 #else
     const char *name   = "";
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -72,36 +72,6 @@
 //    0x20000000 |  536870912 - unused
 //    0x40000000 | 1073741824 - unused
 //    0x80000000 | 2147483648 - unused
-//
-// Note: The ResourceMark is to cleanup resource allocated args.
-//   The "while (0)" is so we can use semi-colon at end of RC_TRACE().
-#define RC_TRACE(level, args) \
-  if ((TraceRedefineClasses & level) != 0) { \
-    ResourceMark rm; \
-    tty->print("RedefineClasses-0x%x: ", level); \
-    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); \
-    tty->print("RedefineClasses-0x%x: ", level); \
-    tty->print_cr args; \
-  } while (0)
-
-#define RC_TRACE_MESG(args) \
-  { \
-    ResourceMark rm; \
-    tty->print("RedefineClasses: "); \
-    tty->print_cr args; \
-  } while (0)
 
 // Macro for checking if TraceRedefineClasses has a specific bit
 // enabled. Returns true if the bit specified by level is set.
@@ -120,16 +90,49 @@
 #define RC_TRACE_IN_RANGE(low, high) \
 (((TraceRedefineClasses & ((high << 1) - 1)) & ~(low - 1)) != 0)
 
-// Timer support macros. Only do timer operations if timer tracing
-// is enabled. The "while (0)" is so we can use semi-colon at end of
-// the macro.
-#define RC_TIMER_START(t) \
+// Note: The ResourceMark is to cleanup resource allocated args.
+// The "do {...} while (0)" is so we can use semi-colon at end of RC_TRACE().
+#define RC_TRACE(level, args) do { \
+  if (RC_TRACE_ENABLED(level)) { \
+    ResourceMark rm; \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print_cr args; \
+  } \
+} while (0)
+
+#define RC_TRACE_NO_CR(level, args) do { \
+  if (RC_TRACE_ENABLED(level)) { \
+    ResourceMark rm; \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print args; \
+  } \
+} while (0)
+
+#define RC_TRACE_WITH_THREAD(level, thread, args) do { \
+  if (RC_TRACE_ENABLED(level)) { \
+    ResourceMark rm(thread); \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print_cr args; \
+  } \
+} while (0)
+
+#define RC_TRACE_MESG(args) do { \
+  ResourceMark rm; \
+  tty->print("RedefineClasses: "); \
+  tty->print_cr args; \
+} while (0)
+
+// Timer support macros. Only do timer operations if timer tracing is enabled.
+// The "do {...} while (0)" is so we can use semi-colon at end of the macro.
+#define RC_TIMER_START(t) do { \
   if (RC_TRACE_ENABLED(0x00000004)) { \
     t.start(); \
-  } while (0)
-#define RC_TIMER_STOP(t) \
+  } \
+} while (0)
+#define RC_TIMER_STOP(t) do { \
   if (RC_TRACE_ENABLED(0x00000004)) { \
     t.stop(); \
-  } while (0)
+  } \
+} while (0)
 
 #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSESTRACE_HPP
--- a/src/share/vm/prims/jvmtiTrace.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/jvmtiTrace.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -43,10 +43,10 @@
 
 // Support tracing except in product build on the client compiler
 #ifndef PRODUCT
-#define JVMTI_TRACE 1
+#define JVMTI_TRACE
 #else
 #ifdef COMPILER2
-#define JVMTI_TRACE 1
+#define JVMTI_TRACE
 #endif
 #endif
 
--- a/src/share/vm/prims/methodHandles.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/methodHandles.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -105,14 +105,15 @@
 
 // import java_lang_invoke_MemberName.*
 enum {
-  IS_METHOD      = java_lang_invoke_MemberName::MN_IS_METHOD,
-  IS_CONSTRUCTOR = java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR,
-  IS_FIELD       = java_lang_invoke_MemberName::MN_IS_FIELD,
-  IS_TYPE        = java_lang_invoke_MemberName::MN_IS_TYPE,
+  IS_METHOD            = java_lang_invoke_MemberName::MN_IS_METHOD,
+  IS_CONSTRUCTOR       = java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR,
+  IS_FIELD             = java_lang_invoke_MemberName::MN_IS_FIELD,
+  IS_TYPE              = java_lang_invoke_MemberName::MN_IS_TYPE,
+  CALLER_SENSITIVE     = java_lang_invoke_MemberName::MN_CALLER_SENSITIVE,
   REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT,
   REFERENCE_KIND_MASK  = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
-  SEARCH_SUPERCLASSES = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES,
-  SEARCH_INTERFACES   = java_lang_invoke_MemberName::MN_SEARCH_INTERFACES,
+  SEARCH_SUPERCLASSES  = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES,
+  SEARCH_INTERFACES    = java_lang_invoke_MemberName::MN_SEARCH_INTERFACES,
   ALL_KINDS      = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE
 };
 
@@ -207,10 +208,15 @@
     vmindex = m->vtable_index();
   }
 
-  java_lang_invoke_MemberName::set_flags(mname_oop,    flags);
+  // @CallerSensitive annotation detected
+  if (m->caller_sensitive()) {
+    flags |= CALLER_SENSITIVE;
+  }
+
+  java_lang_invoke_MemberName::set_flags(   mname_oop, flags);
   java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
-  java_lang_invoke_MemberName::set_vmindex(mname_oop,  vmindex);   // vtable/itable index
-  java_lang_invoke_MemberName::set_clazz(mname_oop,    receiver_limit->java_mirror());
+  java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex);   // vtable/itable index
+  java_lang_invoke_MemberName::set_clazz(   mname_oop, receiver_limit->java_mirror());
   // Note:  name and type can be lazily computed by resolve_MemberName,
   // if Java code needs them as resolved String and MethodType objects.
   // The clazz must be eagerly stored, because it provides a GC
@@ -940,6 +946,7 @@
     template(java_lang_invoke_MemberName,MN_IS_CONSTRUCTOR) \
     template(java_lang_invoke_MemberName,MN_IS_FIELD) \
     template(java_lang_invoke_MemberName,MN_IS_TYPE) \
+    template(java_lang_invoke_MemberName,MN_CALLER_SENSITIVE) \
     template(java_lang_invoke_MemberName,MN_SEARCH_SUPERCLASSES) \
     template(java_lang_invoke_MemberName,MN_SEARCH_INTERFACES) \
     template(java_lang_invoke_MemberName,MN_REFERENCE_KIND_SHIFT) \
--- a/src/share/vm/prims/unsafe.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -116,7 +116,11 @@
 inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
   jlong byte_offset = field_offset_to_byte_offset(field_offset);
   // Don't allow unsafe to be used to read or write the header word of oops
+  // unless running GRAAL which wants to read the misc word for example when
+  // interpreting computeHashCode().
+#ifndef GRAAL
   assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header");
+#endif
 #ifdef ASSERT
   if (p != NULL) {
     assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
@@ -868,7 +872,7 @@
   env->ThrowNew(cls, msg);
 }
 
-static jclass Unsafe_DefineClass(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
+static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
   {
     // Code lifted from JDK 1.3 ClassLoader.c
 
@@ -939,6 +943,15 @@
 }
 
 
+UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
+  UnsafeWrapper("Unsafe_DefineClass");
+  {
+    ThreadToNativeFromVM ttnfv(thread);
+    return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
+  }
+UNSAFE_END
+
+
 UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length))
   UnsafeWrapper("Unsafe_DefineClass");
   {
@@ -949,20 +962,11 @@
     jobject loader = (caller == NULL) ? NULL : JVM_GetClassLoader(env, caller);
     jobject pd     = (caller == NULL) ? NULL : JVM_GetProtectionDomain(env, caller);
 
-    return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
+    return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
   }
 UNSAFE_END
 
 
-UNSAFE_ENTRY(jclass, Unsafe_DefineClass1(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
-  UnsafeWrapper("Unsafe_DefineClass");
-  {
-    ThreadToNativeFromVM ttnfv(thread);
-
-    return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
-  }
-UNSAFE_END
-
 #define DAC_Args CLS"[B["OBJ
 // define a class but do not make it known to the class loader or system dictionary
 // - host_class:  supplies context for linkage, access control, protection domain, and class loader
@@ -1323,7 +1327,7 @@
 #define THR LANG"Throwable;"
 
 #define DC0_Args LANG"String;[BII"
-#define DC1_Args DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
+#define DC_Args  DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -1352,10 +1356,8 @@
 
 
 
-// %%% These are temporarily supported until the SDK sources
-// contain the necessarily updated Unsafe.java.
+// These are the methods for 1.4.0
 static JNINativeMethod methods_140[] = {
-
     {CC"getObject",        CC"("OBJ"I)"OBJ"",   FN_PTR(Unsafe_GetObject140)},
     {CC"putObject",        CC"("OBJ"I"OBJ")V",  FN_PTR(Unsafe_SetObject140)},
 
@@ -1381,12 +1383,10 @@
 
     {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
     {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
-//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
-//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
     {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
 
-    {CC"fieldOffset",        CC"("FLD")I",               FN_PTR(Unsafe_FieldOffset)}, //deprecated
-    {CC"staticFieldBase",    CC"("CLS")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromClass)}, //deprecated
+    {CC"fieldOffset",        CC"("FLD")I",               FN_PTR(Unsafe_FieldOffset)},
+    {CC"staticFieldBase",    CC"("CLS")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromClass)},
     {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
     {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
     {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
@@ -1394,16 +1394,15 @@
     {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
 
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
-    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
+    {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
     {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
     {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)}
 };
 
-// These are the old methods prior to the JSR 166 changes in 1.5.0
+// These are the methods prior to the JSR 166 changes in 1.5.0
 static JNINativeMethod methods_141[] = {
-
     {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
     {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
 
@@ -1429,8 +1428,6 @@
 
     {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
     {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
-//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
-//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
     {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
 
     {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
@@ -1443,7 +1440,7 @@
     {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
 
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
-    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
+    {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
     {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
     {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
@@ -1451,9 +1448,8 @@
 
 };
 
-// These are the old methods prior to the JSR 166 changes in 1.6.0
+// These are the methods prior to the JSR 166 changes in 1.6.0
 static JNINativeMethod methods_15[] = {
-
     {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
     {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
     {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObjectVolatile)},
@@ -1482,8 +1478,6 @@
 
     {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
     {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
-//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
-//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
     {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
 
     {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
@@ -1496,7 +1490,7 @@
     {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
 
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
-    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
+    {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
     {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
     {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
@@ -1509,14 +1503,69 @@
 
 };
 
-// These are the correct methods, moving forward:
-static JNINativeMethod methods[] = {
-
+// These are the methods for 1.6.0 and 1.7.0
+static JNINativeMethod methods_16[] = {
     {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
     {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
     {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObjectVolatile)},
     {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObjectVolatile)},
 
+    DECLARE_GETSETOOP(Boolean, Z),
+    DECLARE_GETSETOOP(Byte, B),
+    DECLARE_GETSETOOP(Short, S),
+    DECLARE_GETSETOOP(Char, C),
+    DECLARE_GETSETOOP(Int, I),
+    DECLARE_GETSETOOP(Long, J),
+    DECLARE_GETSETOOP(Float, F),
+    DECLARE_GETSETOOP(Double, D),
+
+    DECLARE_GETSETNATIVE(Byte, B),
+    DECLARE_GETSETNATIVE(Short, S),
+    DECLARE_GETSETNATIVE(Char, C),
+    DECLARE_GETSETNATIVE(Int, I),
+    DECLARE_GETSETNATIVE(Long, J),
+    DECLARE_GETSETNATIVE(Float, F),
+    DECLARE_GETSETNATIVE(Double, D),
+
+    {CC"getAddress",         CC"("ADR")"ADR,             FN_PTR(Unsafe_GetNativeAddress)},
+    {CC"putAddress",         CC"("ADR""ADR")V",          FN_PTR(Unsafe_SetNativeAddress)},
+
+    {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
+    {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
+    {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
+
+    {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
+    {CC"staticFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_StaticFieldOffset)},
+    {CC"staticFieldBase",    CC"("FLD")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromField)},
+    {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
+    {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
+    {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
+    {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
+    {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
+
+    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
+    {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
+    {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
+    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
+    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
+    {CC"tryMonitorEnter",    CC"("OBJ")Z",               FN_PTR(Unsafe_TryMonitorEnter)},
+    {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
+    {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
+    {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
+    {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z",      FN_PTR(Unsafe_CompareAndSwapLong)},
+    {CC"putOrderedObject",   CC"("OBJ"J"OBJ")V",         FN_PTR(Unsafe_SetOrderedObject)},
+    {CC"putOrderedInt",      CC"("OBJ"JI)V",             FN_PTR(Unsafe_SetOrderedInt)},
+    {CC"putOrderedLong",     CC"("OBJ"JJ)V",             FN_PTR(Unsafe_SetOrderedLong)},
+    {CC"park",               CC"(ZJ)V",                  FN_PTR(Unsafe_Park)},
+    {CC"unpark",             CC"("OBJ")V",               FN_PTR(Unsafe_Unpark)}
+};
+
+// These are the methods for 1.8.0
+static JNINativeMethod methods_18[] = {
+    {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
+    {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
+    {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObjectVolatile)},
+    {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObjectVolatile)},
 
     DECLARE_GETSETOOP(Boolean, Z),
     DECLARE_GETSETOOP(Byte, B),
@@ -1540,8 +1589,6 @@
 
     {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
     {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
-//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
-//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
     {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
 
     {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
@@ -1553,8 +1600,7 @@
     {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
     {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
 
-    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
-    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
+    {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
     {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
     {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
@@ -1566,23 +1612,12 @@
     {CC"putOrderedObject",   CC"("OBJ"J"OBJ")V",         FN_PTR(Unsafe_SetOrderedObject)},
     {CC"putOrderedInt",      CC"("OBJ"JI)V",             FN_PTR(Unsafe_SetOrderedInt)},
     {CC"putOrderedLong",     CC"("OBJ"JJ)V",             FN_PTR(Unsafe_SetOrderedLong)},
-    {CC"loadFence",          CC"()V",                    FN_PTR(Unsafe_LoadFence)},
-    {CC"storeFence",         CC"()V",                    FN_PTR(Unsafe_StoreFence)},
-    {CC"fullFence",          CC"()V",                    FN_PTR(Unsafe_FullFence)},
     {CC"park",               CC"(ZJ)V",                  FN_PTR(Unsafe_Park)},
     {CC"unpark",             CC"("OBJ")V",               FN_PTR(Unsafe_Unpark)}
-
-//    {CC"getLoadAverage",     CC"([DI)I",                 FN_PTR(Unsafe_Loadavg)},
-
-//    {CC"prefetchRead",       CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
-//    {CC"prefetchWrite",      CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
-//    {CC"prefetchReadStatic", CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
-//    {CC"prefetchWriteStatic",CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
-
 };
 
 JNINativeMethod loadavg_method[] = {
-    {CC"getLoadAverage",            CC"([DI)I",                 FN_PTR(Unsafe_Loadavg)}
+    {CC"getLoadAverage",     CC"([DI)I",                 FN_PTR(Unsafe_Loadavg)}
 };
 
 JNINativeMethod prefetch_methods[] = {
@@ -1592,7 +1627,7 @@
     {CC"prefetchWriteStatic",CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
 };
 
-JNINativeMethod memcopy_methods[] = {
+JNINativeMethod memcopy_methods_17[] = {
     {CC"copyMemory",         CC"("OBJ"J"OBJ"JJ)V",       FN_PTR(Unsafe_CopyMemory2)},
     {CC"setMemory",          CC"("OBJ"JJB)V",            FN_PTR(Unsafe_SetMemory2)}
 };
@@ -1610,6 +1645,12 @@
     {CC"shouldBeInitialized",CC"("CLS")Z",               FN_PTR(Unsafe_ShouldBeInitialized)},
 };
 
+JNINativeMethod fence_methods[] = {
+    {CC"loadFence",          CC"()V",                    FN_PTR(Unsafe_LoadFence)},
+    {CC"storeFence",         CC"()V",                    FN_PTR(Unsafe_StoreFence)},
+    {CC"fullFence",          CC"()V",                    FN_PTR(Unsafe_FullFence)},
+};
+
 #undef CC
 #undef FN_PTR
 
@@ -1622,12 +1663,32 @@
 #undef MTH
 #undef THR
 #undef DC0_Args
-#undef DC1_Args
+#undef DC_Args
 
 #undef DECLARE_GETSETOOP
 #undef DECLARE_GETSETNATIVE
 
 
+/**
+ * Helper method to register native methods.
+ */
+static bool register_natives(const char* message, JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
+  int status = env->RegisterNatives(clazz, methods, nMethods);
+  if (status < 0 || env->ExceptionOccurred()) {
+    if (PrintMiscellaneous && (Verbose || WizardMode)) {
+      tty->print_cr("Unsafe:  failed registering %s", message);
+    }
+    env->ExceptionClear();
+    return false;
+  } else {
+    if (PrintMiscellaneous && (Verbose || WizardMode)) {
+      tty->print_cr("Unsafe:  successfully registered %s", message);
+    }
+    return true;
+  }
+}
+
+
 // This one function is exported, used by NativeLookup.
 // The Unsafe_xxx functions above are called only from the interpreter.
 // The optimizer looks at names and signatures to recognize
@@ -1637,83 +1698,57 @@
   UnsafeWrapper("JVM_RegisterUnsafeMethods");
   {
     ThreadToNativeFromVM ttnfv(thread);
-    {
-      env->RegisterNatives(unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
-      if (env->ExceptionOccurred()) {
-        if (PrintMiscellaneous && (Verbose || WizardMode)) {
-          tty->print_cr("Warning:  SDK 1.6 Unsafe.loadavg not found.");
-        }
-        env->ExceptionClear();
-      }
-    }
+
+    // Unsafe methods
     {
-      env->RegisterNatives(unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
-      if (env->ExceptionOccurred()) {
-        if (PrintMiscellaneous && (Verbose || WizardMode)) {
-          tty->print_cr("Warning:  SDK 1.6 Unsafe.prefetchRead/Write not found.");
-        }
-        env->ExceptionClear();
+      bool success = false;
+      // We need to register the 1.6 methods first because the 1.8 methods would register fine on 1.7 and 1.6
+      if (!success) {
+        success = register_natives("1.6 methods",   env, unsafecls, methods_16,  sizeof(methods_16)/sizeof(JNINativeMethod));
+      }
+      if (!success) {
+        success = register_natives("1.8 methods",   env, unsafecls, methods_18,  sizeof(methods_18)/sizeof(JNINativeMethod));
+      }
+      if (!success) {
+        success = register_natives("1.5 methods",   env, unsafecls, methods_15,  sizeof(methods_15)/sizeof(JNINativeMethod));
+      }
+      if (!success) {
+        success = register_natives("1.4.1 methods", env, unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
       }
+      if (!success) {
+        success = register_natives("1.4.0 methods", env, unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
+      }
+      guarantee(success, "register unsafe natives");
     }
+
+    // Unsafe.getLoadAverage
+    register_natives("1.6 loadavg method", env, unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
+
+    // Prefetch methods
+    register_natives("1.6 prefetch methods", env, unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
+
+    // Memory copy methods
     {
-      env->RegisterNatives(unsafecls, memcopy_methods, sizeof(memcopy_methods)/sizeof(JNINativeMethod));
-      if (env->ExceptionOccurred()) {
-        if (PrintMiscellaneous && (Verbose || WizardMode)) {
-          tty->print_cr("Warning:  SDK 1.7 Unsafe.copyMemory not found.");
-        }
-        env->ExceptionClear();
-        env->RegisterNatives(unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
-        if (env->ExceptionOccurred()) {
-          if (PrintMiscellaneous && (Verbose || WizardMode)) {
-            tty->print_cr("Warning:  SDK 1.5 Unsafe.copyMemory not found.");
-          }
-          env->ExceptionClear();
-        }
+      bool success = false;
+      if (!success) {
+        success = register_natives("1.7 memory copy methods", env, unsafecls, memcopy_methods_17, sizeof(memcopy_methods_17)/sizeof(JNINativeMethod));
+      }
+      if (!success) {
+        success = register_natives("1.5 memory copy methods", env, unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
       }
     }
+
+    // Unsafe.defineAnonymousClass
     if (EnableInvokeDynamic) {
-      env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
-      if (env->ExceptionOccurred()) {
-        if (PrintMiscellaneous && (Verbose || WizardMode)) {
-          tty->print_cr("Warning:  SDK 1.7 Unsafe.defineClass (anonymous version) not found.");
-        }
-        env->ExceptionClear();
-      }
-    }
-    if (EnableInvokeDynamic) {
-      env->RegisterNatives(unsafecls, lform_methods, sizeof(lform_methods)/sizeof(JNINativeMethod));
-      if (env->ExceptionOccurred()) {
-        if (PrintMiscellaneous && (Verbose || WizardMode)) {
-          tty->print_cr("Warning:  SDK 1.7 LambdaForm support in Unsafe not found.");
-        }
-        env->ExceptionClear();
-      }
+      register_natives("1.7 define anonymous class method", env, unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
     }
-    int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
-    if (env->ExceptionOccurred()) {
-      if (PrintMiscellaneous && (Verbose || WizardMode)) {
-        tty->print_cr("Warning:  SDK 1.6 version of Unsafe not found.");
-      }
-      env->ExceptionClear();
-      // %%% For now, be backward compatible with an older class:
-      status = env->RegisterNatives(unsafecls, methods_15, sizeof(methods_15)/sizeof(JNINativeMethod));
+
+    // Unsafe.shouldBeInitialized
+    if (EnableInvokeDynamic) {
+      register_natives("1.7 LambdaForm support", env, unsafecls, lform_methods, sizeof(lform_methods)/sizeof(JNINativeMethod));
     }
-    if (env->ExceptionOccurred()) {
-      if (PrintMiscellaneous && (Verbose || WizardMode)) {
-        tty->print_cr("Warning:  SDK 1.5 version of Unsafe not found.");
-      }
-      env->ExceptionClear();
-      // %%% For now, be backward compatible with an older class:
-      status = env->RegisterNatives(unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
-    }
-    if (env->ExceptionOccurred()) {
-      if (PrintMiscellaneous && (Verbose || WizardMode)) {
-        tty->print_cr("Warning:  SDK 1.4.1 version of Unsafe not found.");
-      }
-      env->ExceptionClear();
-      // %%% For now, be backward compatible with an older class:
-      status = env->RegisterNatives(unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
-    }
-    guarantee(status == 0, "register unsafe natives");
+
+    // Fence methods
+    register_natives("1.8 fence methods", env, unsafecls, fence_methods, sizeof(fence_methods)/sizeof(JNINativeMethod));
   }
 JVM_END
--- a/src/share/vm/prims/whitebox.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/prims/whitebox.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -49,6 +49,7 @@
 #endif // INCLUDE_NMT
 
 #include "compiler/compileBroker.hpp"
+#include "runtime/compilationPolicy.hpp"
 
 bool WhiteBox::_used = false;
 
@@ -118,45 +119,46 @@
 #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;
+WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
+  jlong addr = 0;
 
-  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
-    return false;
+  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
+    addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
   }
 
-  // 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;
+  return addr;
 WB_END
 
 // Free the memory allocated by NMTAllocTest
-WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env))
+WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
+  os::free((void*)(uintptr_t)mem, mtTest);
+WB_END
 
-  if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) {
-    return false;
+WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
+  jlong addr = 0;
+
+  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
+    addr = (jlong)(uintptr_t)os::reserve_memory(size);
+    MemTracker::record_virtual_memory_type((address)addr, mtTest);
   }
 
-  os::free(nmtMtTest1, mtTest);
-  nmtMtTest1 = NULL;
-  os::free(nmtMtTest2, mtTest);
-  nmtMtTest2 = NULL;
-  os::free(nmtMtTest3, mtTest);
-  nmtMtTest3 = NULL;
+  return addr;
+WB_END
+
 
-  return true;
+WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::commit_memory((char *)(uintptr_t)addr, size);
+  MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
+WB_END
+
+WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::uncommit_memory((char *)(uintptr_t)addr, size);
+WB_END
+
+WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::release_memory((char *)(uintptr_t)addr, size);
 WB_END
 
 // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
@@ -213,11 +215,11 @@
   return (code->is_alive() && !code->is_marked_for_deoptimization());
 WB_END
 
-WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method))
+WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
   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();
+  return CompilationPolicy::can_be_compiled(mh, comp_level);
 WB_END
 
 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
@@ -241,7 +243,7 @@
   mh->set_not_compilable();
 WB_END
 
-WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
+WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(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();
@@ -254,6 +256,71 @@
          CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
 WB_END
 
+
+WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(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->force_inline();
+  mh->set_force_inline(value == JNI_TRUE);
+  return result;
+WB_END
+
+WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
+  MutexLockerEx mu(Compile_lock);
+  return (mh->queued_for_compilation() || nm != NULL);
+WB_END
+
+WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  MutexLockerEx mu(Compile_lock);
+  MethodData* mdo = mh->method_data();
+
+  if (mdo != NULL) {
+    mdo->init();
+    ResourceMark rm;
+    int arg_count = mdo->method()->size_of_parameters();
+    for (int i = 0; i < arg_count; i++) {
+      mdo->set_arg_modified(i, 0);
+    }
+  }
+
+  mh->backedge_counter()->init();
+  mh->invocation_counter()->init();
+  mh->set_interpreter_invocation_count(0);
+  mh->set_interpreter_throwout_count(0);
+  mh->clear_not_c1_compilable();
+  mh->clear_not_c2_compilable();
+  mh->clear_not_c2_osr_compilable();
+  NOT_PRODUCT(mh->set_compiled_invocation_count(0));
+
+#ifdef TIERED
+  mh->set_rate(0.0F);
+  mh->set_prev_event_count(0);
+  mh->set_prev_time(0);
+#endif
+WB_END
+
+WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
+  ResourceMark rm(THREAD);
+  int len;
+  jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len);
+  oop found_string = StringTable::the_table()->lookup(name, len);
+  if (found_string == NULL) {
+        return false;
+  }
+  return true;
+WB_END
+
+
+WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
+  Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
+  Universe::heap()->collect(GCCause::_last_ditch_collection);
+WB_END
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -322,27 +389,39 @@
   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
 #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},
+  {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
+  {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
+  {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
+  {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
+  {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
+  {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
+  {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",
+  {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)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"testSetDontInlineMethod",
+      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_TestSetDontInlineMethod},
   {CC"getMethodCompilationLevel",
       CC"(Ljava/lang/reflect/Method;)I",              (void*)&WB_GetMethodCompilationLevel},
   {CC"getCompileQueuesSize",
       CC"()I",                                        (void*)&WB_GetCompileQueuesSize},
+  {CC"testSetForceInlineMethod",
+      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_TestSetForceInlineMethod},
+  {CC"enqueueMethodForCompilation",
+      CC"(Ljava/lang/reflect/Method;I)Z",             (void*)&WB_EnqueueMethodForCompilation},
+  {CC"clearMethodState",
+      CC"(Ljava/lang/reflect/Method;)V",              (void*)&WB_ClearMethodState},
+  {CC"isInStringTable",   CC"(Ljava/lang/String;)Z",  (void*)&WB_IsInStringTable  },
+  {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
 };
 
 #undef CC
--- a/src/share/vm/runtime/arguments.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -264,6 +264,7 @@
   { "CMSRevisitStackSize",           JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "PrintRevisitStats",             JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseVectoredExceptions",         JDK_Version::jdk(8), JDK_Version::jdk(9) },
+  { "UseSplitVerifier",              JDK_Version::jdk(8), JDK_Version::jdk(9) },
 #ifdef PRODUCT
   { "DesiredMethodLimit",
                            JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
@@ -1178,7 +1179,6 @@
     set_parnew_gc_flags();
   }
 
-  // MaxHeapSize is aligned down in collectorPolicy
   size_t max_heap = align_size_down(MaxHeapSize,
                                     CardTableRS::ct_max_alignment_constraint());
 
@@ -1216,10 +1216,6 @@
     }
 
     // Code along this path potentially sets NewSize and OldSize
-
-    assert(max_heap >= InitialHeapSize, "Error");
-    assert(max_heap >= NewSize, "Error");
-
     if (PrintGCDetails && Verbose) {
       // Too early to use gclog_or_tty
       tty->print_cr("CMS set min_heap_size: " SIZE_FORMAT
@@ -1390,6 +1386,40 @@
   return false;
 }
 
+void Arguments::set_use_compressed_oops() {
+#ifndef ZERO
+#ifdef _LP64
+  // MaxHeapSize is not set up properly at this point, but
+  // the only value that can override MaxHeapSize if we are
+  // to use UseCompressedOops is InitialHeapSize.
+  size_t max_heap_size = MAX2(MaxHeapSize, InitialHeapSize);
+
+  if (max_heap_size <= max_heap_for_compressed_oops()) {
+#if !defined(COMPILER1) || defined(TIERED)
+    if (FLAG_IS_DEFAULT(UseCompressedOops)) {
+      FLAG_SET_ERGO(bool, UseCompressedOops, true);
+    }
+#endif
+#ifdef _WIN64
+    if (UseLargePages && UseCompressedOops) {
+      // Cannot allocate guard pages for implicit checks in indexed addressing
+      // mode, when large pages are specified on windows.
+      // This flag could be switched ON if narrow oop base address is set to 0,
+      // see code in Universe::initialize_heap().
+      Universe::set_narrow_oop_use_implicit_null_checks(false);
+    }
+#endif //  _WIN64
+  } else {
+    if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) {
+      warning("Max heap size too large for Compressed Oops");
+      FLAG_SET_DEFAULT(UseCompressedOops, false);
+      FLAG_SET_DEFAULT(UseCompressedKlassPointers, false);
+    }
+  }
+#endif // _LP64
+#endif // ZERO
+}
+
 void Arguments::set_ergonomics_flags() {
 
   if (os::is_server_class_machine()) {
@@ -1419,30 +1449,7 @@
 
 #ifndef ZERO
 #ifdef _LP64
-  // Check that UseCompressedOops can be set with the max heap size allocated
-  // by ergonomics.
-  if (MaxHeapSize <= max_heap_for_compressed_oops()) {
-#if !defined(COMPILER1) || defined(TIERED)
-    if (FLAG_IS_DEFAULT(UseCompressedOops)) {
-      FLAG_SET_ERGO(bool, UseCompressedOops, true);
-    }
-#endif
-#ifdef _WIN64
-    if (UseLargePages && UseCompressedOops) {
-      // Cannot allocate guard pages for implicit checks in indexed addressing
-      // mode, when large pages are specified on windows.
-      // This flag could be switched ON if narrow oop base address is set to 0,
-      // see code in Universe::initialize_heap().
-      Universe::set_narrow_oop_use_implicit_null_checks(false);
-    }
-#endif //  _WIN64
-  } else {
-    if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) {
-      warning("Max heap size too large for Compressed Oops");
-      FLAG_SET_DEFAULT(UseCompressedOops, false);
-      FLAG_SET_DEFAULT(UseCompressedKlassPointers, false);
-    }
-  }
+  set_use_compressed_oops();
   // UseCompressedOops must be on for UseCompressedKlassPointers to be on.
   if (!UseCompressedOops) {
     if (UseCompressedKlassPointers) {
@@ -1555,6 +1562,15 @@
   }
 }
 
+julong Arguments::limit_by_allocatable_memory(julong limit) {
+  julong max_allocatable;
+  julong result = limit;
+  if (os::has_allocatable_memory_limit(&max_allocatable)) {
+    result = MIN2(result, max_allocatable / MaxVirtMemFraction);
+  }
+  return result;
+}
+
 void Arguments::set_heap_size() {
   if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
     // Deprecated flag
@@ -1593,12 +1609,12 @@
       }
       reasonable_max = MIN2(reasonable_max, max_coop_heap);
     }
-    reasonable_max = os::allocatable_physical_memory(reasonable_max);
+    reasonable_max = limit_by_allocatable_memory(reasonable_max);
 
     if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
       // An initial heap size was specified on the command line,
       // so be sure that the maximum size is consistent.  Done
-      // after call to allocatable_physical_memory because that
+      // after call to limit_by_allocatable_memory because that
       // method might reduce the allocation size.
       reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
     }
@@ -1618,14 +1634,14 @@
 
     reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);
 
-    reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum);
+    reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum);
 
     julong reasonable_initial = phys_mem / InitialRAMFraction;
 
     reasonable_initial = MAX2(reasonable_initial, reasonable_minimum);
     reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
 
-    reasonable_initial = os::allocatable_physical_memory(reasonable_initial);
+    reasonable_initial = limit_by_allocatable_memory(reasonable_initial);
 
     if (PrintGCDetails && Verbose) {
       // Cannot use gclog_or_tty yet.
@@ -1747,11 +1763,15 @@
   return false;
 }
 
+#if !INCLUDE_ALL_GCS
+#ifdef ASSERT
 static bool verify_serial_gc_flags() {
   return (UseSerialGC &&
         !(UseParNewGC || (UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC ||
           UseParallelGC || UseParallelOldGC));
 }
+#endif // ASSERT
+#endif // INCLUDE_ALL_GCS
 
 // check if do gclog rotation
 // +UseGCLogFileRotation is a must,
@@ -1822,6 +1842,13 @@
   }
 }
 
+void Arguments::check_deprecated_gc_flags() {
+  if (FLAG_IS_CMDLINE(MaxGCMinorPauseMillis)) {
+    warning("Using MaxGCMinorPauseMillis as minor pause goal is deprecated"
+            "and will likely be removed in future release");
+  }
+}
+
 // Check stack pages settings
 bool Arguments::check_stack_pages()
 {
@@ -1992,11 +2019,12 @@
   // than just disable the lock verification. This will be fixed under
   // bug 4788986.
   if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
-    if (VerifyGCStartAt == 0) {
+    if (VerifyDuringStartup) {
       warning("Heap verification at start-up disabled "
               "(due to current incompatibility with FLSVerifyAllHeapReferences)");
-      VerifyGCStartAt = 1;      // Disable verification at start-up
+      VerifyDuringStartup = false; // Disable verification at start-up
     }
+
     if (VerifyBeforeExit) {
       warning("Heap verification at shutdown disabled "
               "(due to current incompatibility with FLSVerifyAllHeapReferences)");
@@ -2328,10 +2356,12 @@
         }
 #if !INCLUDE_JVMTI
         if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
-          warning("profiling and debugging agents are not supported in this VM");
-        } else
+          jio_fprintf(defaultStream::error_stream(),
+            "Profiling and debugging agents are not supported in this VM\n");
+          return JNI_ERR;
+        }
 #endif // !INCLUDE_JVMTI
-          add_init_library(name, options);
+        add_init_library(name, options);
       }
     // -agentlib and -agentpath
     } else if (match_option(option, "-agentlib:", &tail) ||
@@ -2348,16 +2378,19 @@
         }
 #if !INCLUDE_JVMTI
         if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
-          warning("profiling and debugging agents are not supported in this VM");
-        } else
+          jio_fprintf(defaultStream::error_stream(),
+            "Profiling and debugging agents are not supported in this VM\n");
+          return JNI_ERR;
+        }
 #endif // !INCLUDE_JVMTI
         add_init_agent(name, options, is_absolute_path);
-
       }
     // -javaagent
     } else if (match_option(option, "-javaagent:", &tail)) {
 #if !INCLUDE_JVMTI
-      warning("Instrumentation agents are not supported in this VM");
+      jio_fprintf(defaultStream::error_stream(),
+        "Instrumentation agents are not supported in this VM\n");
+      return JNI_ERR;
 #else
       if(tail != NULL) {
         char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
@@ -2498,8 +2531,9 @@
 #if INCLUDE_FPROF
       _has_profile = true;
 #else // INCLUDE_FPROF
-      // do we have to exit?
-      warning("Flat profiling is not supported in this VM.");
+      jio_fprintf(defaultStream::error_stream(),
+        "Flat profiling is not supported in this VM.\n");
+      return JNI_ERR;
 #endif // INCLUDE_FPROF
     // -Xaprof
     } else if (match_option(option, "-Xaprof", &tail)) {
@@ -2533,8 +2567,9 @@
 #if INCLUDE_MANAGEMENT
         FLAG_SET_CMDLINE(bool, ManagementServer, true);
 #else
-        vm_exit_during_initialization(
-            "-Dcom.sun.management is not supported in this VM.", NULL);
+        jio_fprintf(defaultStream::output_stream(),
+          "-Dcom.sun.management is not supported in this VM.\n");
+        return JNI_ERR;
 #endif
       }
     // -Xint
@@ -2547,16 +2582,10 @@
     } else if (match_option(option, "-Xcomp", &tail)) {
       // for testing the compiler; turn off all flags that inhibit compilation
           set_mode_flags(_comp);
-
     // -Xshare:dump
     } else if (match_option(option, "-Xshare:dump", &tail)) {
-#if !INCLUDE_CDS
-      vm_exit_during_initialization(
-          "Dumping a shared archive is not supported in this VM.", NULL);
-#else
       FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true);
       set_mode_flags(_int);     // Prevent compilation, which creates objects
-#endif
     // -Xshare:on
     } else if (match_option(option, "-Xshare:on", &tail)) {
       FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
@@ -2569,7 +2598,6 @@
     } else if (match_option(option, "-Xshare:off", &tail)) {
       FLAG_SET_CMDLINE(bool, UseSharedSpaces, false);
       FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
-
     // -Xverify
     } else if (match_option(option, "-Xverify", &tail)) {
       if (strcmp(tail, ":all") == 0 || strcmp(tail, "") == 0) {
@@ -2650,9 +2678,7 @@
       initHeapSize = MIN2(total_memory / (julong)2,
                           total_memory - (julong)160*M);
 
-      // Make sure that if we have a lot of memory we cap the 32 bit
-      // process space.  The 64bit VM version of this function is a nop.
-      initHeapSize = os::allocatable_physical_memory(initHeapSize);
+      initHeapSize = limit_by_allocatable_memory(initHeapSize);
 
       if (FLAG_IS_DEFAULT(MaxHeapSize)) {
          FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
@@ -2883,8 +2909,9 @@
       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);
+        jio_fprintf(defaultStream::error_stream(),
+          "ManagementServer is not supported in this VM.\n");
+        return JNI_ERR;
 #endif // INCLUDE_MANAGEMENT
     } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
       // Skip -XX:Flags= since that case has already been handled
@@ -3136,6 +3163,7 @@
   }                                                                   \
 } while(0)
 
+#if !INCLUDE_ALL_GCS
 static void force_serial_gc() {
   FLAG_SET_DEFAULT(UseSerialGC, true);
   FLAG_SET_DEFAULT(CMSIncrementalMode, false);  // special CMS suboption
@@ -3145,6 +3173,7 @@
   UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC);
   UNSUPPORTED_GC_OPTION(UseParNewGC);
 }
+#endif // INCLUDE_ALL_GCS
 
 // Parse entry point called from JNI_CreateJavaVM
 
@@ -3201,7 +3230,9 @@
 #if INCLUDE_NMT
       MemTracker::init_tracking_options(tail);
 #else
-      warning("Native Memory Tracking is not supported in this VM");
+      jio_fprintf(defaultStream::error_stream(),
+        "Native Memory Tracking is not supported in this VM\n");
+      return JNI_ERR;
 #endif
     }
 
@@ -3320,6 +3351,16 @@
   force_serial_gc();
 #endif // INCLUDE_ALL_GCS
 #if !INCLUDE_CDS
+  if (DumpSharedSpaces || RequireSharedSpaces) {
+    jio_fprintf(defaultStream::error_stream(),
+      "Shared spaces are not supported in this VM\n");
+    return JNI_ERR;
+  }
+  if ((UseSharedSpaces && FLAG_IS_CMDLINE(UseSharedSpaces)) || PrintSharedSpaces) {
+    warning("Shared spaces are not supported in this VM");
+    FLAG_SET_DEFAULT(UseSharedSpaces, false);
+    FLAG_SET_DEFAULT(PrintSharedSpaces, false);
+  }
   no_shared_spaces();
 #endif // INCLUDE_CDS
 
@@ -3358,6 +3399,14 @@
     set_g1_gc_flags();
   }
   check_deprecated_gcs();
+  check_deprecated_gc_flags();
+  if (AssumeMP && !UseSerialGC) {
+    if (FLAG_IS_DEFAULT(ParallelGCThreads) && ParallelGCThreads == 1) {
+      warning("If the number of processors is expected to increase from one, then"
+              " you should configure the number of parallel GC threads appropriately"
+              " using -XX:ParallelGCThreads=N");
+    }
+  }
 #else // INCLUDE_ALL_GCS
   assert(verify_serial_gc_flags(), "SerialGC unset");
 #endif // INCLUDE_ALL_GCS
--- a/src/share/vm/runtime/arguments.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/arguments.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -314,8 +314,12 @@
   // Garbage-First (UseG1GC)
   static void set_g1_gc_flags();
   // GC ergonomics
+  static void set_use_compressed_oops();
   static void set_ergonomics_flags();
   static void set_shared_spaces_flags();
+  // limits the given memory size by the maximum amount of memory this process is
+  // currently allowed to allocate or reserve.
+  static julong limit_by_allocatable_memory(julong size);
   // Setup heap size
   static void set_heap_size();
   // Based on automatic selection criteria, should the
@@ -422,6 +426,7 @@
   // Check for consistency in the selection of the garbage collector.
   static bool check_gc_consistency();
   static void check_deprecated_gcs();
+  static void check_deprecated_gc_flags();
   // Check consistecy or otherwise of VM argument settings
   static bool check_vm_args_consistency();
   // Check stack pages settings
--- a/src/share/vm/runtime/compilationPolicy.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -130,9 +130,10 @@
   }
   if (comp_level == CompLevel_all) {
     return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization);
-  } else {
+  } else if (is_compile(comp_level)) {
     return !m->is_not_compilable(comp_level);
   }
+  return false;
 }
 
 bool CompilationPolicy::is_compilation_enabled() {
--- a/src/share/vm/runtime/compilationPolicy.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -96,7 +96,7 @@
   void reset_counter_for_back_branch_event(methodHandle method);
 public:
   NonTieredCompPolicy() : _compiler_count(0) { }
-  virtual CompLevel initial_compile_level() { return CompLevel_initial_compile; }
+  virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; }
   virtual int compiler_count(CompLevel comp_level);
   virtual void do_safepoint_work();
   virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);
--- a/src/share/vm/runtime/deoptimization.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -457,6 +457,7 @@
                                                                                                     callee_parameters,
                                                                                                     callee_locals,
                                                                                                     index == 0,
+                                                                                                    index == array->frames() - 1,
                                                                                                     popframe_extra_args);
     // This pc doesn't have to be perfect just good enough to identify the frame
     // as interpreted so the skeleton frame will be walkable
--- a/src/share/vm/runtime/frame.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/frame.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -1070,7 +1070,12 @@
 
   // First consult the ADLC on where it puts parameter 0 for this signature.
   VMReg reg = SharedRuntime::name_for_receiver();
-  oop r = *caller.oopmapreg_to_location(reg, reg_map);
+  oop* oop_adr = caller.oopmapreg_to_location(reg, reg_map);
+  if (oop_adr == NULL) {
+    guarantee(oop_adr != NULL, "bad register save location");
+    return NULL;
+  }
+  oop r = *oop_adr;
   assert(Universe::heap()->is_in_or_null(r), err_msg("bad receiver: " INTPTR_FORMAT " (" INTX_FORMAT ")", (intptr_t) r, (intptr_t) r));
   return r;
 }
--- a/src/share/vm/runtime/globals.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -471,6 +471,9 @@
   lp64_product(intx, ObjectAlignmentInBytes, 8,                             \
           "Default object alignment in bytes, 8 is minimum")                \
                                                                             \
+  product(bool, AssumeMP, false,                                            \
+          "Instruct the VM to assume multiple processors are available")    \
+                                                                            \
   /* UseMembar is theoretically a temp flag used for memory barrier         \
    * removal testing.  It was supposed to be removed before FCS but has     \
    * been re-added (see 6401008) */                                         \
@@ -693,9 +696,6 @@
   product(bool, UseCompilerSafepoints, true,                                \
           "Stop at safepoints in compiled code")                            \
                                                                             \
-  product(bool, UseSplitVerifier, true,                                     \
-          "use split verifier with StackMapTable attributes")               \
-                                                                            \
   product(bool, FailOverToOldVerifier, true,                                \
           "fail over to old verifier when split verifier fails")            \
                                                                             \
@@ -883,6 +883,11 @@
   diagnostic(bool, PrintNMTStatistics, false,                               \
           "Print native memory tracking summary data if it is on")          \
                                                                             \
+  diagnostic(bool, AutoShutdownNMT, true,                                   \
+          "Automatically shutdown native memory tracking under stress "     \
+          "situation. When set to false, native memory tracking tries to "  \
+          "stay alive at the expense of JVM performance")                   \
+                                                                            \
   diagnostic(bool, LogCompilation, false,                                   \
           "Log compilation activity in detail to hotspot.log or LogFile")   \
                                                                             \
@@ -1419,6 +1424,10 @@
           "How much the GC can expand the eden by while the GC locker  "    \
           "is active (as a percentage)")                                    \
                                                                             \
+  diagnostic(intx, GCLockerRetryAllocationCount, 2,                         \
+          "Number of times to retry allocations when"                       \
+          " blocked by the GC locker")                                      \
+                                                                            \
   develop(bool, UseCMSAdaptiveFreeLists, true,                              \
           "Use Adaptive Free Lists in the CMS generation")                  \
                                                                             \
@@ -1768,6 +1777,10 @@
   manageable(intx, CMSWaitDuration, 2000,                                   \
           "Time in milliseconds that CMS thread waits for young GC")        \
                                                                             \
+  develop(uintx, CMSCheckInterval, 1000,                                    \
+          "Interval in milliseconds that CMS thread checks if it "          \
+          "should start a collection cycle")                                \
+                                                                            \
   product(bool, CMSYield, true,                                             \
           "Yield between steps of concurrent mark & sweep")                 \
                                                                             \
@@ -1971,6 +1984,10 @@
   product(uintx, InitialRAMFraction, 64,                                    \
           "Fraction (1/n) of real memory used for initial heap size")       \
                                                                             \
+  develop(uintx, MaxVirtMemFraction, 2,                                     \
+          "Maximum fraction (1/n) of virtual memory used for ergonomically" \
+          "determining maximum heap size")                                  \
+                                                                            \
   product(bool, UseAutoGCSelectPolicy, false,                               \
           "Use automatic collection selection policy")                      \
                                                                             \
@@ -2123,6 +2140,10 @@
   product(intx, PrefetchFieldsAhead, -1,                                    \
           "How many fields ahead to prefetch in oop scan (<= 0 means off)") \
                                                                             \
+  diagnostic(bool, VerifyDuringStartup, false,                              \
+          "Verify memory system before executing any Java code "            \
+          "during VM initialization")                                       \
+                                                                            \
   diagnostic(bool, VerifyBeforeExit, trueInDebug,                           \
           "Verify system before exiting")                                   \
                                                                             \
@@ -2528,7 +2549,7 @@
           "disable locking assertions (for speed)")                         \
                                                                             \
   product(bool, RangeCheckElimination, true,                                \
-          "Split loop iterations to eliminate range checks")                \
+          "Eliminate range checks")                                         \
                                                                             \
   develop_pd(bool, UncommonNullCast,                                        \
           "track occurrences of null in casts; adjust compiler tactics")    \
@@ -2921,6 +2942,10 @@
           "if non-zero, start verifying C heap after Nth call to "          \
           "malloc/realloc/free")                                            \
                                                                             \
+  diagnostic(uintx, MallocMaxTestWords,     0,                              \
+          "if non-zero, max # of Words that malloc/realloc can allocate "   \
+          "(for testing only)")                                             \
+                                                                            \
   product_pd(intx, TypeProfileWidth,                                        \
           "number of receiver types to record in call/cast profile")        \
                                                                             \
@@ -3312,10 +3337,10 @@
           "ConcurrentMarkSweep thread runs at critical scheduling priority")\
                                                                             \
   /* compiler debugging */                                                  \
-  notproduct(intx, CompileTheWorldStartAt,     1,                           \
+  develop(intx, CompileTheWorldStartAt, 1,                                  \
           "First class to consider when using +CompileTheWorld")            \
                                                                             \
-  notproduct(intx, CompileTheWorldStopAt, max_jint,                         \
+  develop(intx, CompileTheWorldStopAt, max_jint,                            \
           "Last class to consider when using +CompileTheWorld")             \
                                                                             \
   develop(intx, NewCodeParameter,      0,                                   \
@@ -3585,8 +3610,9 @@
   product(uintx, SharedMiscCodeSize,    120*K,                              \
           "Size of the shared miscellaneous code area (in bytes)")          \
                                                                             \
-  product(uintx, SharedDummyBlockSize, 0,                                   \
-          "Size of dummy block used to shift heap addresses (in bytes)")    \
+  product(uintx, SharedBaseAddress, LP64_ONLY(32*G)                         \
+          NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)),                           \
+          "Address to allocate shared memory region for class data")        \
                                                                             \
   diagnostic(bool, EnableInvokeDynamic, true,                               \
           "support JSR 292 (method handles, invokedynamic, "                \
@@ -3660,7 +3686,15 @@
           "Enable internal testing APIs")                                   \
                                                                             \
   product(bool, PrintGCCause, true,                                         \
-          "Include GC cause in GC logging")
+          "Include GC cause in GC logging")                                 \
+                                                                            \
+  product(bool , AllowNonVirtualCalls, false,                               \
+          "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
+                                                                            \
+  experimental(uintx, ArrayAllocatorMallocLimit,                            \
+          SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx),                        \
+          "Allocation less than this value will be allocated "              \
+          "using malloc. Larger allocations will use mmap.")
 
 /*
  *  Macros for factoring of globals
--- a/src/share/vm/runtime/init.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/init.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -132,15 +132,6 @@
   javaClasses_init();   // must happen after vtable initialization
   stubRoutines_init2(); // note: StubRoutines need 2-phase init
 
-  // Although we'd like to, we can't easily do a heap verify
-  // here because the main thread isn't yet a JavaThread, so
-  // its TLAB may not be made parseable from the usual interfaces.
-  if (VerifyBeforeGC && !UseTLAB &&
-      Universe::heap()->total_collections() >= VerifyGCStartAt) {
-    Universe::heap()->prepare_for_verify();
-    Universe::verify();   // make sure we're starting with a clean slate
-  }
-
   // All the flags that get adjusted by VM_Version_init and os::init_2
   // have been set so dump the flags now.
   if (PrintFlagsFinal) {
--- a/src/share/vm/runtime/javaCalls.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -412,7 +412,7 @@
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       entry_point = method->adapter()->get_i2c_entry();
     } else {
-      THROW(vmSymbols::MethodInvalidatedException());
+      THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException());
     }
   }
 #endif
--- a/src/share/vm/runtime/os.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/os.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -80,6 +80,8 @@
 julong os::free_bytes = 0;          // # of bytes freed
 #endif
 
+static juint cur_malloc_words = 0;  // current size for MallocMaxTestWords
+
 void os_init_globals() {
   // Called from init_globals().
   // See Threads::create_vm() in thread.cpp, and init.cpp.
@@ -570,6 +572,26 @@
 }
 #endif
 
+//
+// This function supports testing of the malloc out of memory
+// condition without really running the system out of memory.
+//
+static u_char* testMalloc(size_t alloc_size) {
+  assert(MallocMaxTestWords > 0, "sanity check");
+
+  if ((cur_malloc_words + (alloc_size / BytesPerWord)) > MallocMaxTestWords) {
+    return NULL;
+  }
+
+  u_char* ptr = (u_char*)::malloc(alloc_size);
+
+  if (ptr != NULL) {
+    Atomic::add(((jint) (alloc_size / BytesPerWord)),
+                (volatile jint *) &cur_malloc_words);
+  }
+  return ptr;
+}
+
 void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
   NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
   NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
@@ -579,11 +601,22 @@
     // if NULL is returned the calling functions assume out of memory.
     size = 1;
   }
-  if (size > size + space_before + space_after) { // Check for rollover.
+
+  const size_t alloc_size = size + space_before + space_after;
+
+  if (size > alloc_size) { // Check for rollover.
     return NULL;
   }
+
   NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
-  u_char* ptr = (u_char*)::malloc(size + space_before + space_after);
+
+  u_char* ptr;
+
+  if (MallocMaxTestWords > 0) {
+    ptr = testMalloc(alloc_size);
+  } else {
+    ptr = (u_char*)::malloc(alloc_size);
+  }
 
 #ifdef ASSERT
   if (ptr == NULL) return NULL;
--- a/src/share/vm/runtime/os.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/os.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -180,11 +180,11 @@
   // Interface for detecting multiprocessor system
   static inline bool is_MP() {
     assert(_processor_count > 0, "invalid processor count");
-    return _processor_count > 1;
+    return _processor_count > 1 || AssumeMP;
   }
   static julong available_memory();
   static julong physical_memory();
-  static julong allocatable_physical_memory(julong size);
+  static bool has_allocatable_memory_limit(julong* limit);
   static bool is_server_class_machine();
 
   // number of CPUs
--- a/src/share/vm/runtime/safepoint.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/safepoint.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -735,6 +735,9 @@
 // Exception handlers
 
 #ifndef PRODUCT
+
+#ifdef SPARC
+
 #ifdef _LP64
 #define PTR_PAD ""
 #else
@@ -755,7 +758,6 @@
                 newptr, is_oop?"oop":"   ", (wasoop && !is_oop) ? "STALE" : ((wasoop==false&&is_oop==false&&oldptr !=newptr)?"STOMP":"     "));
 }
 
-#ifdef SPARC
 static void print_me(intptr_t *new_sp, intptr_t *old_sp, bool *was_oops) {
 #ifdef _LP64
   tty->print_cr("--------+------address-----+------before-----------+-------after----------+");
--- a/src/share/vm/runtime/sharedRuntime.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -83,6 +83,7 @@
 #endif
 
 // Shared stub locations
+RuntimeStub*        SharedRuntime::_deoptimized_installed_code_blob;
 RuntimeStub*        SharedRuntime::_wrong_method_blob;
 RuntimeStub*        SharedRuntime::_ic_miss_blob;
 RuntimeStub*        SharedRuntime::_resolve_opt_virtual_call_blob;
@@ -101,6 +102,7 @@
 
 //----------------------------generate_stubs-----------------------------------
 void SharedRuntime::generate_stubs() {
+  _deoptimized_installed_code_blob     = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_deoptimized_installed_code), "deoptimized_installed_code");
   _wrong_method_blob                   = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method),         "wrong_method_stub");
   _ic_miss_blob                        = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub");
   _resolve_opt_virtual_call_blob       = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C),  "resolve_opt_virtual_call");
@@ -969,6 +971,11 @@
 
 
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
+#ifdef GRAAL
+  if (!obj->klass()->has_finalizer()) {
+    return;
+  }
+#endif
   assert(obj->is_oop(), "must be a valid oop");
   assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
   InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
@@ -1345,6 +1352,12 @@
   return callee_method->verified_code_entry();
 JRT_END
 
+// Installed code has been deoptimized
+JRT_BLOCK_ENTRY(address, SharedRuntime::handle_deoptimized_installed_code(JavaThread* thread))
+  JavaThread* THREAD = thread;
+  ThreadInVMfromJava tiv(THREAD);
+  THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+JRT_END
 
 // Handle call site that has been made non-entrant
 JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread))
--- a/src/share/vm/runtime/sharedRuntime.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -55,6 +55,7 @@
 
   // Shared stub locations
 
+  static RuntimeStub*        _deoptimized_installed_code_blob;
   static RuntimeStub*        _wrong_method_blob;
   static RuntimeStub*        _ic_miss_blob;
   static RuntimeStub*        _resolve_opt_virtual_call_blob;
@@ -209,6 +210,11 @@
     return _wrong_method_blob->entry_point();
   }
 
+  static address get_deoptimized_installed_code_stub() {
+    assert(_deoptimized_installed_code_blob!= NULL, "oops");
+    return _deoptimized_installed_code_blob->entry_point();
+  }
+
 #ifdef COMPILER2
   static void generate_uncommon_trap_blob(void);
   static UncommonTrapBlob* uncommon_trap_blob()                  { return _uncommon_trap_blob; }
@@ -486,6 +492,9 @@
   static address handle_wrong_method(JavaThread* thread);
   static address handle_wrong_method_ic_miss(JavaThread* thread);
 
+  // handle deoptimized installed code
+  static address handle_deoptimized_installed_code(JavaThread* thread);
+
 #ifndef PRODUCT
 
   // Collect and print inline cache miss statistics
--- a/src/share/vm/runtime/stubCodeGenerator.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/stubCodeGenerator.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -87,7 +87,7 @@
     CodeBuffer* cbuf = _masm->code();
     CodeBlob*   blob = CodeCache::find_blob_unsafe(cbuf->insts()->start());
     if (blob != NULL) {
-      blob->set_comments(cbuf->comments());
+      blob->set_strings(cbuf->strings());
     }
     bool saw_first = false;
     StubCodeDesc* toprint[1000];
--- a/src/share/vm/runtime/synchronizer.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/synchronizer.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -449,8 +449,6 @@
 // and explicit fences (barriers) to control for architectural reordering performed
 // by the CPU(s) or platform.
 
-static int  MBFence (int x) { OrderAccess::fence(); return x; }
-
 struct SharedGlobals {
     // These are highly shared mostly-read variables.
     // To avoid false-sharing they need to be the sole occupants of a $ line.
@@ -813,6 +811,7 @@
   }
 
   if (owner != NULL) {
+    // owning_thread_from_monitor_owner() may also return NULL here
     return Threads::owning_thread_from_monitor_owner(owner, doLock);
   }
 
@@ -1638,11 +1637,6 @@
 
 #ifndef PRODUCT
 
-void ObjectSynchronizer::trace_locking(Handle locking_obj, bool is_compiled,
-                                       bool is_method, bool is_locking) {
-  // Don't know what to do here
-}
-
 // Verify all monitors in the monitor cache, the verification is weak.
 void ObjectSynchronizer::verify() {
   ObjectMonitor* block = gBlockList;
--- a/src/share/vm/runtime/synchronizer.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/synchronizer.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -121,7 +121,6 @@
   static void oops_do(OopClosure* f);
 
   // debugging
-  static void trace_locking(Handle obj, bool is_compiled, bool is_method, bool is_locking) PRODUCT_RETURN;
   static void verify() PRODUCT_RETURN;
   static int  verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
 
--- a/src/share/vm/runtime/thread.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/thread.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -3426,12 +3426,6 @@
   // real raw monitor. VM is setup enough here for raw monitor enter.
   JvmtiExport::transition_pending_onload_raw_monitors();
 
-  if (VerifyBeforeGC &&
-      Universe::heap()->total_collections() >= VerifyGCStartAt) {
-    Universe::heap()->prepare_for_verify();
-    Universe::verify();   // make sure we're starting with a clean slate
-  }
-
   // Fully start NMT
   MemTracker::start();
 
@@ -3455,6 +3449,11 @@
   }
 
   assert (Universe::is_fully_initialized(), "not initialized");
+  if (VerifyDuringStartup) {
+    VM_Verify verify_op(false /* silent */);   // make sure we're starting with a clean slate
+    VMThread::execute(&verify_op);
+  }
+
   EXCEPTION_MARK;
 
   // At this point, the Universe is initialized, but we have not executed
@@ -4064,6 +4063,7 @@
   if (version == JNI_VERSION_1_2) return JNI_TRUE;
   if (version == JNI_VERSION_1_4) return JNI_TRUE;
   if (version == JNI_VERSION_1_6) return JNI_TRUE;
+  if (version == JNI_VERSION_1_8) return JNI_TRUE;
   return JNI_FALSE;
 }
 
@@ -4288,7 +4288,9 @@
       if (owner == (address)p) return p;
     }
   }
-  assert(UseHeavyMonitors == false, "Did not find owning Java thread with UseHeavyMonitors enabled");
+  // Cannot assert on lack of success here since this function may be
+  // used by code that is trying to report useful problem information
+  // like deadlock detection.
   if (UseHeavyMonitors) return NULL;
 
   //
@@ -4306,7 +4308,7 @@
       }
     }
   }
-  assert(the_owner != NULL, "Did not find owning Java thread for lock word address");
+  // cannot assert on lack of success here; see above comment
   return the_owner;
 }
 
--- a/src/share/vm/runtime/thread.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/thread.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -1312,6 +1312,7 @@
   void enable_stack_red_zone();
   void disable_stack_red_zone();
 
+  inline bool stack_guard_zone_unused();
   inline bool stack_yellow_zone_disabled();
   inline bool stack_yellow_zone_enabled();
 
@@ -1785,6 +1786,10 @@
   return (CompilerThread*)this;
 }
 
+inline bool JavaThread::stack_guard_zone_unused() {
+  return _stack_guard_state == stack_guard_unused;
+}
+
 inline bool JavaThread::stack_yellow_zone_disabled() {
   return _stack_guard_state == stack_guard_yellow_disabled;
 }
--- a/src/share/vm/runtime/vframe.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vframe.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -391,40 +391,27 @@
 // Step back n frames, skip any pseudo frames in between.
 // This function is used in Class.forName, Class.newInstance, Method.Invoke,
 // AccessController.doPrivileged.
-//
-// NOTE that in JDK 1.4 this has been exposed to Java as
-// sun.reflect.Reflection.getCallerClass(), which can be inlined.
-// Inlined versions must match this routine's logic.
-// Native method prefixing logic does not need to match since
-// the method names don't match and inlining will not occur.
-// See, for example,
-// Parse::inline_native_Reflection_getCallerClass in
-// opto/library_call.cpp.
 void vframeStreamCommon::security_get_caller_frame(int depth) {
-  bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
+  assert(depth >= 0, err_msg("invalid depth: %d", depth));
+  for (int n = 0; !at_end(); security_next()) {
+    if (!method()->is_ignored_by_security_stack_walk()) {
+      if (n == depth) {
+        // We have reached the desired depth; return.
+        return;
+      }
+      n++;  // this is a non-skipped frame; count it against the depth
+    }
+  }
+  // NOTE: At this point there were not enough frames on the stack
+  // to walk to depth.  Callers of this method have to check for at_end.
+}
 
-  while (!at_end()) {
-    if (Universe::reflect_invoke_cache()->is_same_method(method())) {
-      // This is Method.invoke() -- skip it
-    } else if (use_new_reflection &&
-              method()->method_holder()
-                 ->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
-      // This is an auxilary frame -- skip it
-    } else if (method()->is_method_handle_intrinsic() ||
-               method()->is_compiled_lambda_form()) {
-      // This is an internal adapter frame for method handles -- skip it
-    } else {
-      // This is non-excluded frame, we need to count it against the depth
-      if (depth-- <= 0) {
-        // we have reached the desired depth, we are done
-        break;
-      }
-    }
-    if (method()->is_prefixed_native()) {
-      skip_prefixed_method_and_wrappers();
-    } else {
-      next();
-    }
+
+void vframeStreamCommon::security_next() {
+  if (method()->is_prefixed_native()) {
+    skip_prefixed_method_and_wrappers();  // calls next()
+  } else {
+    next();
   }
 }
 
--- a/src/share/vm/runtime/vframe.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vframe.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -336,6 +336,7 @@
       _frame = _frame.sender(&_reg_map);
     } while (!fill_from_frame());
   }
+  void security_next();
 
   bool at_end() const { return _mode == at_end_mode; }
 
--- a/src/share/vm/runtime/vframeArray.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vframeArray.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -160,6 +160,7 @@
                                          int callee_locals,
                                          frame* caller,
                                          bool is_top_frame,
+                                         bool is_bottom_frame,
                                          int exec_mode) {
   JavaThread* thread = (JavaThread*) Thread::current();
 
@@ -278,7 +279,8 @@
                                  callee_locals,
                                  caller,
                                  iframe(),
-                                 is_top_frame);
+                                 is_top_frame,
+                                 is_bottom_frame);
 
   // Update the pc in the frame object and overwrite the temporary pc
   // we placed in the skeletal frame now that we finally know the
@@ -456,6 +458,7 @@
                                       int callee_parameters,
                                       int callee_locals,
                                       bool is_top_frame,
+                                      bool is_bottom_frame,
                                       int popframe_extra_stack_expression_els) const {
   assert(method()->max_locals() == locals()->size(), "just checking");
   int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors();
@@ -467,7 +470,8 @@
                                       caller_actual_parameters,
                                       callee_parameters,
                                       callee_locals,
-                                      is_top_frame);
+                                      is_top_frame,
+                                      is_bottom_frame);
 }
 
 
@@ -558,7 +562,7 @@
 
   // Do the unpacking of interpreter frames; the frame at index 0 represents the top activation, so it has no callee
   // Unpack the frames from the oldest (frames() -1) to the youngest (0)
-  frame caller_frame = me;
+  frame* caller_frame = &me;
   for (index = frames() - 1; index >= 0 ; index--) {
     vframeArrayElement* elem = element(index);  // caller
     int callee_parameters, callee_locals;
@@ -578,13 +582,14 @@
     elem->unpack_on_stack(caller_actual_parameters,
                           callee_parameters,
                           callee_locals,
-                          &caller_frame,
+                          caller_frame,
                           index == 0,
+                          index == frames() - 1,
                           exec_mode);
     if (index == frames() - 1) {
       Deoptimization::unwind_callee_save_values(elem->iframe(), this);
     }
-    caller_frame = *elem->iframe();
+    caller_frame = elem->iframe();
     caller_actual_parameters = callee_parameters;
   }
   deallocate_monitor_chunks();
--- a/src/share/vm/runtime/vframeArray.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vframeArray.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -88,6 +88,7 @@
   int on_stack_size(int caller_actual_parameters,
                     int callee_parameters,
                     int callee_locals,
+                    bool is_bottom_frame,
                     bool is_top_frame,
                     int popframe_extra_stack_expression_els) const;
 
@@ -97,6 +98,7 @@
                        int callee_locals,
                        frame* caller,
                        bool is_top_frame,
+                       bool is_bottom_frame,
                        int exec_mode);
 
 #ifndef PRODUCT
--- a/src/share/vm/runtime/vmStructs.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -336,7 +336,6 @@
   nonstatic_field(Klass,                       _access_flags,                                 AccessFlags)                           \
   nonstatic_field(Klass,                       _subklass,                                     Klass*)                                \
   nonstatic_field(Klass,                       _next_sibling,                                 Klass*)                                \
-  nonproduct_nonstatic_field(Klass,            _verify_count,                                 int)                                   \
   nonstatic_field(Klass,                       _alloc_count,                                  juint)                                 \
   nonstatic_field(MethodData,           _size,                                         int)                                   \
   nonstatic_field(MethodData,           _method,                                       Method*)                        \
@@ -479,6 +478,9 @@
                                                                                                                                      \
   nonstatic_field(CardGeneration,              _rs,                                           GenRemSet*)                            \
   nonstatic_field(CardGeneration,              _bts,                                          BlockOffsetSharedArray*)               \
+  nonstatic_field(CardGeneration,              _shrink_factor,                                size_t)                                \
+  nonstatic_field(CardGeneration,              _capacity_at_prologue,                         size_t)                                \
+  nonstatic_field(CardGeneration,              _used_at_prologue,                             size_t)                                \
                                                                                                                                      \
   nonstatic_field(CardTableModRefBS,           _whole_heap,                                   const MemRegion)                       \
   nonstatic_field(CardTableModRefBS,           _guard_index,                                  const size_t)                          \
@@ -549,8 +551,6 @@
   nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
   nonstatic_field(Space,                       _end,                                          HeapWord*)                             \
                                                                                                                                      \
-  nonstatic_field(TenuredGeneration,           _shrink_factor,                                size_t)                                \
-  nonstatic_field(TenuredGeneration,           _capacity_at_prologue,                         size_t)                                \
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _end,                                          HeapWord*)                             \
--- a/src/share/vm/runtime/vm_operations.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vm_operations.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -177,7 +177,8 @@
 }
 
 void VM_Verify::doit() {
-  Universe::verify();
+  Universe::heap()->prepare_for_verify();
+  Universe::verify(_silent);
 }
 
 bool VM_PrintThreads::doit_prologue() {
--- a/src/share/vm/runtime/vm_operations.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vm_operations.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -94,6 +94,7 @@
   template(ReportJavaOutOfMemory)                 \
   template(JFRCheckpoint)                         \
   template(Exit)                                  \
+  template(LinuxDllLoad)                          \
 
 class VM_Operation: public CHeapObj<mtInternal> {
  public:
@@ -300,9 +301,9 @@
 
 class VM_Verify: public VM_Operation {
  private:
-  KlassHandle _dependee;
+  bool _silent;
  public:
-  VM_Verify() {}
+  VM_Verify(bool silent) : _silent(silent) {}
   VMOp_Type type() const { return VMOp_Verify; }
   void doit();
 };
--- a/src/share/vm/runtime/vm_version.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/runtime/vm_version.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -215,6 +215,10 @@
         #define HOTSPOT_BUILD_COMPILER "MS VC++ 8.0 (VS2005)"
       #elif _MSC_VER == 1500
         #define HOTSPOT_BUILD_COMPILER "MS VC++ 9.0 (VS2008)"
+      #elif _MSC_VER == 1600
+        #define HOTSPOT_BUILD_COMPILER "MS VC++ 10.0 (VS2010)"
+      #elif _MSC_VER == 1700
+        #define HOTSPOT_BUILD_COMPILER "MS VC++ 11.0 (VS2012)"
       #else
         #define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER)
       #endif
--- a/src/share/vm/services/memReporter.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/memReporter.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -419,7 +419,7 @@
       _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
       _output->print("%28s", " ");
     } else {
-      _output->print("[" PTR_FORMAT "]%18s", " ");
+      _output->print("[" PTR_FORMAT "]%18s", pc, " ");
     }
 
     _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)",
@@ -596,7 +596,7 @@
         _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
         _output->print("%28s", " ");
       } else {
-        _output->print("[" PTR_FORMAT "]%18s", " ");
+        _output->print("[" PTR_FORMAT "]%18s", pc, " ");
       }
     }
 
--- a/src/share/vm/services/memTracker.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/memTracker.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -68,6 +68,7 @@
 volatile jint                   MemTracker::_pooled_recorder_count = 0;
 volatile unsigned long          MemTracker::_processing_generation = 0;
 volatile bool                   MemTracker::_worker_thread_idle = false;
+volatile bool                   MemTracker::_slowdown_calling_thread = false;
 debug_only(intx                 MemTracker::_main_thread_tid = 0;)
 NOT_PRODUCT(volatile jint       MemTracker::_pending_recorder_count = 0;)
 
@@ -126,12 +127,15 @@
   assert(_state == NMT_bootstrapping_multi_thread, "wrong state");
 
   _snapshot = new (std::nothrow)MemSnapshot();
-  if (_snapshot != NULL && !_snapshot->out_of_memory()) {
-    if (start_worker()) {
+  if (_snapshot != NULL) {
+    if (!_snapshot->out_of_memory() && start_worker()) {
       _state = NMT_started;
       NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
       return;
     }
+
+    delete _snapshot;
+    _snapshot = NULL;
   }
 
   // fail to start native memory tracking, shut it down
@@ -364,6 +368,12 @@
     }
 
     if (thread != NULL) {
+      // slow down all calling threads except NMT worker thread, so it
+      // can catch up.
+      if (_slowdown_calling_thread && thread != _worker_thread) {
+        os::yield_all();
+      }
+
       if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
         JavaThread*      java_thread = (JavaThread*)thread;
         JavaThreadState  state = java_thread->thread_state();
@@ -442,6 +452,7 @@
 #define MAX_SAFEPOINTS_TO_SKIP     128
 #define SAFE_SEQUENCE_THRESHOLD    30
 #define HIGH_GENERATION_THRESHOLD  60
+#define MAX_RECORDER_THREAD_RATIO  30
 
 void MemTracker::sync() {
   assert(_tracking_level > NMT_off, "NMT is not enabled");
@@ -487,6 +498,13 @@
         pending_recorders = _global_recorder;
         _global_recorder = NULL;
       }
+
+      // see if NMT has too many outstanding recorder instances, it usually
+      // means that worker thread is lagging behind in processing them.
+      if (!AutoShutdownNMT) {
+        _slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count);
+      }
+
       // check _worker_thread with lock to avoid racing condition
       if (_worker_thread != NULL) {
         _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes());
@@ -529,7 +547,10 @@
   assert(_worker_thread == NULL, "Just Check");
   _worker_thread = new (std::nothrow) MemTrackWorker();
   if (_worker_thread == NULL || _worker_thread->has_error()) {
-    shutdown(NMT_initialization);
+    if (_worker_thread != NULL) {
+      delete _worker_thread;
+      _worker_thread = NULL;
+    }
     return false;
   }
   _worker_thread->start();
--- a/src/share/vm/services/memTracker.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/memTracker.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -84,14 +84,15 @@
    static inline bool baseline() { return false; }
    static inline bool has_baseline() { return false; }
 
+   static inline void set_autoShutdown(bool value) { }
    static void shutdown(ShutdownReason reason) { }
-   static inline bool shutdown_in_progress() {  }
+   static inline bool shutdown_in_progress() { return false; }
    static bool print_memory_usage(BaselineOutputer& out, size_t unit,
-            bool summary_only = true) { }
+            bool summary_only = true) { return false; }
    static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
-            bool summary_only = true) { }
+            bool summary_only = true) { return false; }
 
-   static bool wbtest_wait_for_data_merge() { }
+   static bool wbtest_wait_for_data_merge() { return false; }
 
    static inline void sync() { }
    static inline void thread_exiting(JavaThread* thread) { }
@@ -238,6 +239,16 @@
   // if native memory tracking tracks callsite
   static inline bool track_callsite() { return _tracking_level == NMT_detail; }
 
+  // NMT automatically shuts itself down under extreme situation by default.
+  // When the value is set to false,  NMT will try its best to stay alive,
+  // even it has to slow down VM.
+  static inline void set_autoShutdown(bool value) {
+    AutoShutdownNMT = value;
+    if (AutoShutdownNMT && _slowdown_calling_thread) {
+      _slowdown_calling_thread = false;
+    }
+  }
+
   // shutdown native memory tracking capability. Native memory tracking
   // can be shutdown by VM when it encounters low memory scenarios.
   // Memory tracker should gracefully shutdown itself, and preserve the
@@ -507,6 +518,10 @@
   // although NMT is still procesing current generation, but
   // there is not more recorder to process, set idle state
   static volatile bool             _worker_thread_idle;
+
+  // if NMT should slow down calling thread to allow
+  // worker thread to catch up
+  static volatile bool             _slowdown_calling_thread;
 };
 
 #endif // !INCLUDE_NMT
--- a/src/share/vm/services/memoryService.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/memoryService.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -240,6 +240,7 @@
 void MemoryService::add_generation_memory_pool(Generation* gen,
                                                MemoryManager* major_mgr,
                                                MemoryManager* minor_mgr) {
+  guarantee(gen != NULL, "No generation for memory pool");
   Generation::Name kind = gen->kind();
   int index = _pools_list->length();
 
--- a/src/share/vm/services/nmtDCmd.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/nmtDCmd.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -49,6 +49,9 @@
   _shutdown("shutdown", "request runtime to shutdown itself and free the " \
             "memory used by runtime.",
             "BOOLEAN", false, "false"),
+  _auto_shutdown("autoShutdown", "automatically shutdown itself under "    \
+            "stress situation",
+            "BOOLEAN", true, "true"),
 #ifndef PRODUCT
   _debug("debug", "print tracker statistics. Debug only, not thread safe", \
             "BOOLEAN", false, "false"),
@@ -61,6 +64,7 @@
   _dcmdparser.add_dcmd_option(&_summary_diff);
   _dcmdparser.add_dcmd_option(&_detail_diff);
   _dcmdparser.add_dcmd_option(&_shutdown);
+  _dcmdparser.add_dcmd_option(&_auto_shutdown);
 #ifndef PRODUCT
   _dcmdparser.add_dcmd_option(&_debug);
 #endif
@@ -84,17 +88,19 @@
   }
 
   int nopt = 0;
-  if(_summary.is_set() && _summary.value()) { ++nopt; }
-  if(_detail.is_set() && _detail.value()) { ++nopt; }
-  if(_baseline.is_set() && _baseline.value()) { ++nopt; }
-  if(_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
-  if(_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
-  if(_shutdown.is_set() && _shutdown.value()) { ++nopt; }
+  if (_summary.is_set() && _summary.value()) { ++nopt; }
+  if (_detail.is_set() && _detail.value()) { ++nopt; }
+  if (_baseline.is_set() && _baseline.value()) { ++nopt; }
+  if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
+  if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
+  if (_shutdown.is_set() && _shutdown.value()) { ++nopt; }
+  if (_auto_shutdown.is_set()) { ++nopt; }
+
 #ifndef PRODUCT
-  if(_debug.is_set() && _debug.value()) { ++nopt; }
+  if (_debug.is_set() && _debug.value()) { ++nopt; }
 #endif
 
-  if(nopt > 1) {
+  if (nopt > 1) {
       output()->print_cr("At most one of the following option can be specified: " \
         "summary, detail, baseline, summary.diff, detail.diff, shutdown"
 #ifndef PRODUCT
@@ -156,6 +162,8 @@
     MemTracker::shutdown(MemTracker::NMT_shutdown_user);
     output()->print_cr("Shutdown is in progress, it will take a few moments to " \
       "completely shutdown");
+  } else if (_auto_shutdown.is_set()) {
+    MemTracker::set_autoShutdown(_auto_shutdown.value());
   } else {
     ShouldNotReachHere();
     output()->print_cr("Unknown command");
--- a/src/share/vm/services/nmtDCmd.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/nmtDCmd.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -39,6 +39,7 @@
   DCmdArgument<bool>  _summary_diff;
   DCmdArgument<bool>  _detail_diff;
   DCmdArgument<bool>  _shutdown;
+  DCmdArgument<bool>  _auto_shutdown;
 #ifndef PRODUCT
   DCmdArgument<bool>  _debug;
 #endif
--- a/src/share/vm/services/threadService.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/services/threadService.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -327,8 +327,28 @@
     while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) {
       cycle->add_thread(currentThread);
       if (waitingToLockMonitor != NULL) {
-        currentThread = Threads::owning_thread_from_monitor_owner((address)waitingToLockMonitor->owner(),
-                                                                  false /* no locking needed */);
+        currentThread = Threads::owning_thread_from_monitor_owner(
+                          (address)waitingToLockMonitor->owner(),
+                          false /* no locking needed */);
+        if (currentThread == NULL) {
+          // This function is called at a safepoint so the JavaThread
+          // that owns waitingToLockMonitor should be findable, but
+          // if it is not findable, then the previous currentThread is
+          // blocked permanently. We record this as a deadlock.
+          num_deadlocks++;
+
+          cycle->set_deadlock(true);
+
+          // add this cycle to the deadlocks list
+          if (deadlocks == NULL) {
+            deadlocks = cycle;
+          } else {
+            last->set_next(cycle);
+          }
+          last = cycle;
+          cycle = new DeadlockCycle();
+          break;
+        }
       } else {
         if (concurrent_locks) {
           if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) {
@@ -841,7 +861,17 @@
         owner_desc = " (JVMTI raw monitor),\n  which is held by";
       }
       currentThread = Threads::owning_thread_from_monitor_owner(
-        (address)waitingToLockMonitor->owner(), false /* no locking needed */);
+                        (address)waitingToLockMonitor->owner(),
+                        false /* no locking needed */);
+      if (currentThread == NULL) {
+        // The deadlock was detected at a safepoint so the JavaThread
+        // that owns waitingToLockMonitor should be findable, but
+        // if it is not findable, then the previous currentThread is
+        // blocked permanently.
+        st->print("%s UNKNOWN_owner_addr=" PTR_FORMAT, owner_desc,
+                  (address)waitingToLockMonitor->owner());
+        continue;
+      }
     } else {
       st->print("  waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)",
                 (address)waitingToLockBlocker,
--- a/src/share/vm/utilities/accessFlags.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/accessFlags.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -194,6 +194,9 @@
   void set_is_obsolete()               { atomic_set_bits(JVM_ACC_IS_OBSOLETE);             }
   void set_is_prefixed_native()        { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE);      }
 
+  void clear_not_c1_compilable()       { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE);       }
+  void clear_not_c2_compilable()       { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE);       }
+  void clear_not_c2_osr_compilable()   { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE);   }
   // Klass* flags
   void set_has_vanilla_constructor()   { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
   void set_has_finalizer()             { atomic_set_bits(JVM_ACC_HAS_FINALIZER);           }
--- a/src/share/vm/utilities/bitMap.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/bitMap.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -516,6 +516,10 @@
   return sum;
 }
 
+void BitMap::print_on_error(outputStream* st, const char* prefix) const {
+  st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")",
+      prefix, map(), (char*)map() + (size() >> LogBitsPerByte));
+}
 
 #ifndef PRODUCT
 
--- a/src/share/vm/utilities/bitMap.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/bitMap.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -262,6 +262,7 @@
   bool is_full() const;
   bool is_empty() const;
 
+  void print_on_error(outputStream* st, const char* prefix) const;
 
 #ifndef PRODUCT
  public:
--- a/src/share/vm/utilities/debug.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/debug.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -248,10 +248,6 @@
   report_vm_error(file, line, "ShouldNotReachHere()");
 }
 
-void report_should_not_reach_here2(const char* file, int line, const char* message) {
-  report_vm_error(file, line, "ShouldNotReachHere()", message);
-}
-
 void report_unimplemented(const char* file, int line) {
   report_vm_error(file, line, "Unimplemented()");
 }
@@ -612,18 +608,6 @@
   return  CodeCache::find_nmethod((address)addr);
 }
 
-static address same_page(address x, address y) {
-  intptr_t page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
-    return x;
-  } else if (x > y) {
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  } else {
-    return (address)(intptr_t(y) & page_bits);
-  }
-}
-
-
 // Another interface that isn't ambiguous in dbx.
 // Can we someday rename the other find to hsfind?
 extern "C" void hsfind(intptr_t x) {
--- a/src/share/vm/utilities/debug.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/debug.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -192,12 +192,6 @@
   BREAKPOINT;                                                                \
 } while (0)
 
-#define ShouldNotReachHere2(message)                                         \
-do {                                                                         \
-  report_should_not_reach_here2(__FILE__, __LINE__, message);                \
-  BREAKPOINT;                                                                \
-} while (0)
-
 #define Unimplemented()                                                      \
 do {                                                                         \
   report_unimplemented(__FILE__, __LINE__);                                  \
@@ -218,7 +212,6 @@
                              const char* message);
 void report_should_not_call(const char* file, int line);
 void report_should_not_reach_here(const char* file, int line);
-void report_should_not_reach_here2(const char* file, int line, const char* message);
 void report_unimplemented(const char* file, int line);
 void report_untested(const char* file, int line, const char* message);
 
--- a/src/share/vm/utilities/elfFile.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/elfFile.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -197,4 +197,28 @@
   return NULL;
 }
 
+#ifdef LINUX
+bool ElfFile::specifies_noexecstack() {
+  Elf_Phdr phdr;
+  if (!m_file)  return true;
+
+  if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) {
+    for (int index = 0; index < m_elfHdr.e_phnum; index ++) {
+      if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) {
+        m_status = NullDecoder::file_invalid;
+        return false;
+      }
+      if (phdr.p_type == PT_GNU_STACK) {
+        if (phdr.p_flags == (PF_R | PF_W))  {
+          return true;
+        } else {
+          return false;
+        }
+      }
+    }
+  }
+  return false;
+}
+#endif
+
 #endif // _WINDOWS
--- a/src/share/vm/utilities/elfFile.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/elfFile.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -43,6 +43,7 @@
 
 typedef Elf64_Ehdr      Elf_Ehdr;
 typedef Elf64_Shdr      Elf_Shdr;
+typedef Elf64_Phdr      Elf_Phdr;
 typedef Elf64_Sym       Elf_Sym;
 
 #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
@@ -59,6 +60,7 @@
 
 typedef Elf32_Ehdr      Elf_Ehdr;
 typedef Elf32_Shdr      Elf_Shdr;
+typedef Elf32_Phdr      Elf_Phdr;
 typedef Elf32_Sym       Elf_Sym;
 
 #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
@@ -123,6 +125,14 @@
    ElfFile*  next() const { return m_next; }
    void set_next(ElfFile* file) { m_next = file; }
 
+ public:
+  // Returns true if the elf file is marked NOT to require an executable stack,
+  // or if the file could not be opened.
+  // Returns false if the elf file requires an executable stack, the stack flag
+  // is not set at all, or if the file can not be read.
+  // On systems other than linux it always returns false.
+  bool specifies_noexecstack() NOT_LINUX({ return false; });
+
  protected:
     ElfFile*         m_next;
 
--- a/src/share/vm/utilities/globalDefinitions.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/globalDefinitions.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -355,3 +355,33 @@
 
     return size_t(result);
 }
+
+#ifndef PRODUCT
+
+void GlobalDefinitions::test_globals() {
+  intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 };
+  const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]);
+
+  for (int i = 0; i < num_page_sizes; i++) {
+    intptr_t page_size = page_sizes[i];
+
+    address a_page = (address)(10*page_size);
+
+    // Check that address within page is returned as is
+    assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect");
+
+    // Check that address above page returns start of next page
+    assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect");
+
+    // Check that address below page returns start of page
+    assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect");
+  }
+}
+
+#endif // PRODUCT
--- a/src/share/vm/utilities/globalDefinitions.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -419,6 +419,24 @@
   return align_size_up(offset, HeapWordsPerLong);
 }
 
+// Clamp an address to be within a specific page
+// 1. If addr is on the page it is returned as is
+// 2. If addr is above the page_address the start of the *next* page will be returned
+// 3. Otherwise, if addr is below the page_address the start of the page will be returned
+inline address clamp_address_in_page(address addr, address page_address, intptr_t page_size) {
+  if (align_size_down(intptr_t(addr), page_size) == align_size_down(intptr_t(page_address), page_size)) {
+    // address is in the specified page, just return it as is
+    return addr;
+  } else if (addr > page_address) {
+    // address is above specified page, return start of next page
+    return (address)align_size_down(intptr_t(page_address), page_size) + page_size;
+  } else {
+    // address is below specified page, return start of page
+    return (address)align_size_down(intptr_t(page_address), page_size);
+  }
+}
+
+
 // The expected size in bytes of a cache line, used to pad data structures.
 #define DEFAULT_CACHE_LINE_SIZE 64
 
@@ -827,6 +845,10 @@
   return comp_level == CompLevel_highest_tier;
 }
 
+inline bool is_compile(int comp_level) {
+  return is_c1_compile(comp_level) || is_c2_compile(comp_level);
+}
+
 //----------------------------------------------------------------------------------------------------
 // 'Forward' declarations of frequently used classes
 // (in order to reduce interface dependencies & reduce
@@ -1296,4 +1318,15 @@
   return *(void**)addr;
 }
 
+
+#ifndef PRODUCT
+
+// For unit testing only
+class GlobalDefinitions {
+public:
+  static void test_globals();
+};
+
+#endif // PRODUCT
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP
--- a/src/share/vm/utilities/numberSeq.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/numberSeq.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -245,7 +245,7 @@
 
 void NumberSeq::dump_on(outputStream* s) {
   AbsSeq::dump_on(s);
-  s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f");
+  s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f", _last, _maximum);
 }
 
 void TruncatedSeq::dump_on(outputStream* s) {
--- a/src/share/vm/utilities/taskqueue.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/taskqueue.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -253,6 +253,7 @@
 
 template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
 class GenericTaskQueue: public TaskQueueSuper<N, F> {
+  ArrayAllocator<E, F> _array_allocator;
 protected:
   typedef typename TaskQueueSuper<N, F>::Age Age;
   typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
@@ -314,7 +315,7 @@
 
 template<class E, MEMFLAGS F, unsigned int N>
 void GenericTaskQueue<E, F, N>::initialize() {
-  _elems = NEW_C_HEAP_ARRAY(E, N, F);
+  _elems = _array_allocator.allocate(N);
 }
 
 template<class E, MEMFLAGS F, unsigned int N>
--- a/src/share/vm/utilities/utf8.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/utf8.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -180,11 +180,12 @@
 }
 
 // converts a utf8 string to quoted ascii
-void UTF8::as_quoted_ascii(const char* utf8_str, char* buf, int buflen) {
+void UTF8::as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen) {
   const char *ptr = utf8_str;
+  const char *utf8_end = ptr + utf8_length;
   char* p = buf;
   char* end = buf + buflen;
-  while (*ptr != '\0') {
+  while (ptr < utf8_end) {
     jchar c;
     ptr = UTF8::next(ptr, &c);
     if (c >= 32 && c < 127) {
@@ -196,6 +197,7 @@
       p += 6;
     }
   }
+  assert(p < end, "sanity");
   *p = '\0';
 }
 
--- a/src/share/vm/utilities/utf8.hpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/utf8.hpp	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -45,7 +45,7 @@
   static int quoted_ascii_length(const char* utf8_str, int utf8_length);
 
   // converts a utf8 string to quoted ascii
-  static void as_quoted_ascii(const char* utf8_str, char* buf, int buflen);
+  static void as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen);
 
   // converts a quoted ascii string to utf8 string.  returns the original
   // string unchanged if nothing needs to be done.
--- a/src/share/vm/utilities/vmError.cpp	Thu Apr 04 11:57:04 2013 +0200
+++ b/src/share/vm/utilities/vmError.cpp	Mon Apr 15 08:51:19 2013 +0200
@@ -685,13 +685,7 @@
   STEP(190, "(printing heap information)" )
 
      if (_verbose && Universe::is_fully_initialized()) {
-       // Print heap information before vm abort. As we'd like as much
-       // information as possible in the report we ask for the
-       // extended (i.e., more detailed) version.
-       Universe::print_on(st, true /* extended */);
-       st->cr();
-
-       Universe::heap()->barrier_set()->print_on(st);
+       Universe::heap()->print_on_error(st);
        st->cr();
 
        st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());
--- a/test/compiler/5091921/Test6890943.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/5091921/Test6890943.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -22,26 +22,16 @@
 # questions.
 # 
 # 
-
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "CLASSPATH=${CLASSPATH}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
+
 
 set -x
 
@@ -50,7 +40,7 @@
 cp ${TESTSRC}/output6890943.txt .
 cp ${TESTSRC}/Test6890943.sh .
 
-${TESTJAVA}/bin/javac -d . Test6890943.java
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test6890943.java
 
 ${TESTJAVA}/bin/java -XX:-PrintVMOptions -XX:+IgnoreUnrecognizedVMOptions ${TESTVMOPTS} Test6890943 < input6890943.txt > pretest.out 2>&1
 
--- a/test/compiler/5091921/Test7005594.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/5091921/Test7005594.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -22,26 +22,15 @@
 # questions.
 # 
 # 
-
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "CLASSPATH=${CLASSPATH}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 # Amount of physical memory in megabytes
 MEM=0
@@ -87,7 +76,7 @@
 cp ${TESTSRC}/Test7005594.java .
 cp ${TESTSRC}/Test7005594.sh .
 
-${TESTJAVA}/bin/javac -d . Test7005594.java
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java
 
 ${TESTJAVA}/bin/java ${TESTVMOPTS} -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1
 
--- a/test/compiler/6431242/Test.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6431242/Test.java	Mon Apr 15 08:51:19 2013 +0200
@@ -25,7 +25,7 @@
 /*
  * @test
  * @bug 6431242
- * @run main/othervm -server -XX:+PrintCompilation Test
+ * @run main Test
  */
 
 public class Test{
--- a/test/compiler/6589834/Test_ia32.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6589834/Test_ia32.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @bug 6589834
  * @summary deoptimization problem with -XX:+DeoptimizeALot
  *
- * @run main/othervm -server Test_ia32
+ * @run main Test_ia32
  */
 
 /***************************************************************************************
--- a/test/compiler/6636138/Test1.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6636138/Test1.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @bug 6636138
  * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
  *
- * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init Test1
+ * @run main/othervm -Xbatch -XX:CompileOnly=Test1.init Test1
  */
 
 public class Test1 {
--- a/test/compiler/6636138/Test2.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6636138/Test2.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @bug 6636138
  * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
  *
- * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift Test2
+ * @run main/othervm -Xbatch -XX:CompileOnly=Test2.shift Test2
  */
 
 public class Test2 {
--- a/test/compiler/6795161/Test.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6795161/Test.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @test
  * @bug 6795161
  * @summary Escape analysis leads to data corruption
- * @run main/othervm -server  -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test
  */
 
 class Test_Class_1 {
--- a/test/compiler/6857159/Test6857159.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6857159/Test6857159.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -22,33 +22,22 @@
 # questions.
 # 
 # 
-
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "CLASSPATH=${CLASSPATH}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 set -x
 
 cp ${TESTSRC}/Test6857159.java .
 cp ${TESTSRC}/Test6857159.sh .
 
-${TESTJAVA}/bin/javac -d . Test6857159.java
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test6857159.java
 
 ${TESTJAVA}/bin/java  ${TESTVMOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1
 
--- a/test/compiler/6863420/Test.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6863420/Test.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,17 +27,35 @@
  * @bug 6863420
  * @summary os::javaTimeNanos() go backward on Solaris x86
  *
- * @run main/othervm Test
+ * Notice the internal timeout in timeout thread Test.TOT.
+ * @run main/othervm/timeout=300 Test
  */
 
 public class Test {
+
+    static final int INTERNAL_TIMEOUT=240;
+    static class TOT extends Thread {
+       public void run() {
+           try {
+               Thread.sleep(INTERNAL_TIMEOUT*1000);
+           } catch (InterruptedException ex) {
+           }
+           done = true;
+       }
+    }
+
     static long value = 0;
     static boolean got_backward_time = false;
+    static volatile boolean done = false;
 
     public static void main(String args[]) {
         final int count = 100000;
 
-        for (int numThreads = 1; numThreads <= 32; numThreads++) {
+        TOT tot = new TOT();
+        tot.setDaemon(true);
+        tot.start();
+
+        for (int numThreads = 1; !done && numThreads <= 32; numThreads++) {
             final int numRuns = 1;
             for (int t=1; t <= numRuns; t++) {
                 final int curRun = t;
@@ -48,7 +66,7 @@
                     Runnable thread =
                         new Runnable() {
                             public void run() {
-                                for (long l = 0; l < 100000; l++) {
+                                for (long l = 0; !done && l < 100000; l++) {
                                     final long start = System.nanoTime();
                                     if (value == 12345678) {
                                         System.out.println("Wow!");
--- a/test/compiler/6946040/TestCharShortByteSwap.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/6946040/TestCharShortByteSwap.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @test
  * @bug 6946040
  * @summary Tests Character/Short.reverseBytes and their intrinsics implementation in the server compiler
- * @run main/othervm -Xbatch -server -XX:CompileOnly=.testChar,.testShort TestCharShortByteSwap
+ * @run main/othervm -Xbatch -XX:CompileOnly=.testChar,.testShort TestCharShortByteSwap
  */
 
 // This test must run without any command line arguments.
--- a/test/compiler/7068051/Test7068051.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/7068051/Test7068051.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -22,28 +22,24 @@
 # questions.
 # 
 # 
-
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 set -x
 
-${TESTJAVA}/bin/jar xf ${TESTJAVA}/jre/lib/javaws.jar
-${TESTJAVA}/bin/jar cf foo.jar *
+${COMPILEJAVA}/bin/jar xf ${COMPILEJAVA}/jre/lib/javaws.jar
+${COMPILEJAVA}/bin/jar cf foo.jar *
 cp ${TESTSRC}/Test7068051.java ./
-${TESTJAVA}/bin/jar -uf0 foo.jar Test7068051.java
+${COMPILEJAVA}/bin/jar -uf0 foo.jar Test7068051.java
 
-${TESTJAVA}/bin/javac -d . Test7068051.java
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7068051.java
 
-${TESTJAVA}/bin/java -showversion -Xbatch ${TESTVMOPTS} Test7068051 foo.jar
+${TESTJAVA}/bin/java ${TESTVMOPTS} -showversion -Xbatch Test7068051 foo.jar
 
--- a/test/compiler/7070134/Test7070134.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/7070134/Test7070134.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -22,33 +22,22 @@
 # questions.
 # 
 # 
-
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "CLASSPATH=${CLASSPATH}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 set -x
 
 cp ${TESTSRC}/Stemmer.java .
 cp ${TESTSRC}/words .
 
-${TESTJAVA}/bin/javac -d . Stemmer.java
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Stemmer.java
 
 ${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch Stemmer words > test.out 2>&1
 
--- a/test/compiler/7200264/Test7200264.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/7200264/Test7200264.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -23,50 +23,15 @@
 # 
 # 
 
+## some tests require path to find test source dir
 if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
 echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "CLASSPATH=${CLASSPATH}"
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug"
 
@@ -88,7 +53,7 @@
 fi
 
 cp ${TESTSRC}${FS}TestIntVect.java .
-${TESTJAVA}${FS}bin${FS}javac -d . TestIntVect.java
+${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} -d . TestIntVect.java
 
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1
 
--- a/test/compiler/8000805/Test8000805.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/8000805/Test8000805.java	Mon Apr 15 08:51:19 2013 +0200
@@ -26,7 +26,7 @@
  * @bug 8000805
  * @summary JMM issue: short loads are non-atomic
  *
- * @run main/othervm -server -XX:-TieredCompilation -Xcomp -XX:+PrintCompilation -XX:CompileOnly=Test8000805.loadS2LmaskFF,Test8000805.loadS2Lmask16,Test8000805.loadS2Lmask13,Test8000805.loadUS_signExt,Test8000805.loadB2L_mask8 Test8000805
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -Xcomp -XX:+PrintCompilation -XX:CompileOnly=Test8000805.loadS2LmaskFF,Test8000805.loadS2Lmask16,Test8000805.loadS2Lmask13,Test8000805.loadUS_signExt,Test8000805.loadB2L_mask8 Test8000805
  */
 
 public class Test8000805 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8009761/Test8009761.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,255 @@
+/*
+ * 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 8009761
+ * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates
+ * @run main/othervm -Xmixed -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8009761
+ *
+ */
+
+public class Test8009761 {
+
+    static class UnloadedClass {
+        volatile int i;
+    }
+
+    static Object m1(boolean deopt) {
+        // When running interpreted, on sparc, the caller's stack is
+        // extended for the locals and the caller's frame is restored
+        // on return.
+        long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12,
+        l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24,
+        l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36,
+        l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48,
+        l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60,
+        l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72,
+        l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84,
+        l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96,
+        l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107,
+        l108, l109, l110, l111, l112, l113, l114, l115, l116, l117,
+        l118, l119, l120, l121, l122, l123, l124, l125, l126, l127,
+        l128, l129, l130, l131, l132, l133, l134, l135, l136, l137,
+        l138, l139, l140, l141, l142, l143, l144, l145, l146, l147,
+        l148, l149, l150, l151, l152, l153, l154, l155, l156, l157,
+        l158, l159, l160, l161, l162, l163, l164, l165, l166, l167,
+        l168, l169, l170, l171, l172, l173, l174, l175, l176, l177,
+        l178, l179, l180, l181, l182, l183, l184, l185, l186, l187,
+        l188, l189, l190, l191, l192, l193, l194, l195, l196, l197,
+        l198, l199, l200, l201, l202, l203, l204, l205, l206, l207,
+        l208, l209, l210, l211, l212, l213, l214, l215, l216, l217,
+        l218, l219, l220, l221, l222, l223, l224, l225, l226, l227,
+        l228, l229, l230, l231, l232, l233, l234, l235, l236, l237,
+        l238, l239, l240, l241, l242, l243, l244, l245, l246, l247,
+        l248, l249, l250, l251, l252, l253, l254, l255, l256, l257,
+        l258, l259, l260, l261, l262, l263, l264, l265, l266, l267,
+        l268, l269, l270, l271, l272, l273, l274, l275, l276, l277,
+        l278, l279, l280, l281, l282, l283, l284, l285, l286, l287,
+        l288, l289, l290, l291, l292, l293, l294, l295, l296, l297,
+        l298, l299, l300, l301, l302, l303, l304, l305, l306, l307,
+        l308, l309, l310, l311, l312, l313, l314, l315, l316, l317,
+        l318, l319, l320, l321, l322, l323, l324, l325, l326, l327,
+        l328, l329, l330, l331, l332, l333, l334, l335, l336, l337,
+        l338, l339, l340, l341, l342, l343, l344, l345, l346, l347,
+        l348, l349, l350, l351, l352, l353, l354, l355, l356, l357,
+        l358, l359, l360, l361, l362, l363, l364, l365, l366, l367,
+        l368, l369, l370, l371, l372, l373, l374, l375, l376, l377,
+        l378, l379, l380, l381, l382, l383, l384, l385, l386, l387,
+        l388, l389, l390, l391, l392, l393, l394, l395, l396, l397,
+        l398, l399, l400, l401, l402, l403, l404, l405, l406, l407,
+        l408, l409, l410, l411, l412, l413, l414, l415, l416, l417,
+        l418, l419, l420, l421, l422, l423, l424, l425, l426, l427,
+        l428, l429, l430, l431, l432, l433, l434, l435, l436, l437,
+        l438, l439, l440, l441, l442, l443, l444, l445, l446, l447,
+        l448, l449, l450, l451, l452, l453, l454, l455, l456, l457,
+        l458, l459, l460, l461, l462, l463, l464, l465, l466, l467,
+        l468, l469, l470, l471, l472, l473, l474, l475, l476, l477,
+        l478, l479, l480, l481, l482, l483, l484, l485, l486, l487,
+        l488, l489, l490, l491, l492, l493, l494, l495, l496, l497,
+        l498, l499, l500, l501, l502, l503, l504, l505, l506, l507,
+        l508, l509, l510, l511;
+
+        long ll0, ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, ll9, ll10, ll11, ll12,
+        ll13, ll14, ll15, ll16, ll17, ll18, ll19, ll20, ll21, ll22, ll23, ll24,
+        ll25, ll26, ll27, ll28, ll29, ll30, ll31, ll32, ll33, ll34, ll35, ll36,
+        ll37, ll38, ll39, ll40, ll41, ll42, ll43, ll44, ll45, ll46, ll47, ll48,
+        ll49, ll50, ll51, ll52, ll53, ll54, ll55, ll56, ll57, ll58, ll59, ll60,
+        ll61, ll62, ll63, ll64, ll65, ll66, ll67, ll68, ll69, ll70, ll71, ll72,
+        ll73, ll74, ll75, ll76, ll77, ll78, ll79, ll80, ll81, ll82, ll83, ll84,
+        ll85, ll86, ll87, ll88, ll89, ll90, ll91, ll92, ll93, ll94, ll95, ll96,
+        ll97, ll98, ll99, ll100, ll101, ll102, ll103, ll104, ll105, ll106, ll107,
+        ll108, ll109, ll110, ll111, ll112, ll113, ll114, ll115, ll116, ll117,
+        ll118, ll119, ll120, ll121, ll122, ll123, ll124, ll125, ll126, ll127,
+        ll128, ll129, ll130, ll131, ll132, ll133, ll134, ll135, ll136, ll137,
+        ll138, ll139, ll140, ll141, ll142, ll143, ll144, ll145, ll146, ll147,
+        ll148, ll149, ll150, ll151, ll152, ll153, ll154, ll155, ll156, ll157,
+        ll158, ll159, ll160, ll161, ll162, ll163, ll164, ll165, ll166, ll167,
+        ll168, ll169, ll170, ll171, ll172, ll173, ll174, ll175, ll176, ll177,
+        ll178, ll179, ll180, ll181, ll182, ll183, ll184, ll185, ll186, ll187,
+        ll188, ll189, ll190, ll191, ll192, ll193, ll194, ll195, ll196, ll197,
+        ll198, ll199, ll200, ll201, ll202, ll203, ll204, ll205, ll206, ll207,
+        ll208, ll209, ll210, ll211, ll212, ll213, ll214, ll215, ll216, ll217,
+        ll218, ll219, ll220, ll221, ll222, ll223, ll224, ll225, ll226, ll227,
+        ll228, ll229, ll230, ll231, ll232, ll233, ll234, ll235, ll236, ll237,
+        ll238, ll239, ll240, ll241, ll242, ll243, ll244, ll245, ll246, ll247,
+        ll248, ll249, ll250, ll251, ll252, ll253, ll254, ll255, ll256, ll257,
+        ll258, ll259, ll260, ll261, ll262, ll263, ll264, ll265, ll266, ll267,
+        ll268, ll269, ll270, ll271, ll272, ll273, ll274, ll275, ll276, ll277,
+        ll278, ll279, ll280, ll281, ll282, ll283, ll284, ll285, ll286, ll287,
+        ll288, ll289, ll290, ll291, ll292, ll293, ll294, ll295, ll296, ll297,
+        ll298, ll299, ll300, ll301, ll302, ll303, ll304, ll305, ll306, ll307,
+        ll308, ll309, ll310, ll311, ll312, ll313, ll314, ll315, ll316, ll317,
+        ll318, ll319, ll320, ll321, ll322, ll323, ll324, ll325, ll326, ll327,
+        ll328, ll329, ll330, ll331, ll332, ll333, ll334, ll335, ll336, ll337,
+        ll338, ll339, ll340, ll341, ll342, ll343, ll344, ll345, ll346, ll347,
+        ll348, ll349, ll350, ll351, ll352, ll353, ll354, ll355, ll356, ll357,
+        ll358, ll359, ll360, ll361, ll362, ll363, ll364, ll365, ll366, ll367,
+        ll368, ll369, ll370, ll371, ll372, ll373, ll374, ll375, ll376, ll377,
+        ll378, ll379, ll380, ll381, ll382, ll383, ll384, ll385, ll386, ll387,
+        ll388, ll389, ll390, ll391, ll392, ll393, ll394, ll395, ll396, ll397,
+        ll398, ll399, ll400, ll401, ll402, ll403, ll404, ll405, ll406, ll407,
+        ll408, ll409, ll410, ll411, ll412, ll413, ll414, ll415, ll416, ll417,
+        ll418, ll419, ll420, ll421, ll422, ll423, ll424, ll425, ll426, ll427,
+        ll428, ll429, ll430, ll431, ll432, ll433, ll434, ll435, ll436, ll437,
+        ll438, ll439, ll440, ll441, ll442, ll443, ll444, ll445, ll446, ll447,
+        ll448, ll449, ll450, ll451, ll452, ll453, ll454, ll455, ll456, ll457,
+        ll458, ll459, ll460, ll461, ll462, ll463, ll464, ll465, ll466, ll467,
+        ll468, ll469, ll470, ll471, ll472, ll473, ll474, ll475, ll476, ll477,
+        ll478, ll479, ll480, ll481, ll482, ll483, ll484, ll485, ll486, ll487,
+        ll488, ll489, ll490, ll491, ll492, ll493, ll494, ll495, ll496, ll497,
+        ll498, ll499, ll500, ll501, ll502, ll503, ll504, ll505, ll506, ll507,
+        ll508, ll509, ll510, ll511;
+
+        if (deopt) {
+            UnloadedClass res = new UnloadedClass(); // sufficient to force deopt with c2 but not c1
+            res.i = 0; // forces deopt with c1
+            return res;
+        }
+        return null;
+    }
+
+    static int count = 0;
+
+    static void m2() {
+        // Will be called recursively until a stack overflow
+        // exception. Makes sure it has a lot of locals so that it's
+        // not called a sufficient number of times to trigger
+        // compilation.
+
+        long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12,
+        l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24,
+        l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36,
+        l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48,
+        l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60,
+        l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72,
+        l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84,
+        l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96,
+        l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107,
+        l108, l109, l110, l111, l112, l113, l114, l115, l116, l117,
+        l118, l119, l120, l121, l122, l123, l124, l125, l126, l127,
+        l128, l129, l130, l131, l132, l133, l134, l135, l136, l137,
+        l138, l139, l140, l141, l142, l143, l144, l145, l146, l147,
+        l148, l149, l150, l151, l152, l153, l154, l155, l156, l157,
+        l158, l159, l160, l161, l162, l163, l164, l165, l166, l167,
+        l168, l169, l170, l171, l172, l173, l174, l175, l176, l177,
+        l178, l179, l180, l181, l182, l183, l184, l185, l186, l187,
+        l188, l189, l190, l191, l192, l193, l194, l195, l196, l197,
+        l198, l199, l200, l201, l202, l203, l204, l205, l206, l207,
+        l208, l209, l210, l211, l212, l213, l214, l215, l216, l217,
+        l218, l219, l220, l221, l222, l223, l224, l225, l226, l227,
+        l228, l229, l230, l231, l232, l233, l234, l235, l236, l237,
+        l238, l239, l240, l241, l242, l243, l244, l245, l246, l247,
+        l248, l249, l250, l251, l252, l253, l254, l255, l256, l257,
+        l258, l259, l260, l261, l262, l263, l264, l265, l266, l267,
+        l268, l269, l270, l271, l272, l273, l274, l275, l276, l277,
+        l278, l279, l280, l281, l282, l283, l284, l285, l286, l287,
+        l288, l289, l290, l291, l292, l293, l294, l295, l296, l297,
+        l298, l299, l300, l301, l302, l303, l304, l305, l306, l307,
+        l308, l309, l310, l311, l312, l313, l314, l315, l316, l317,
+        l318, l319, l320, l321, l322, l323, l324, l325, l326, l327,
+        l328, l329, l330, l331, l332, l333, l334, l335, l336, l337,
+        l338, l339, l340, l341, l342, l343, l344, l345, l346, l347,
+        l348, l349, l350, l351, l352, l353, l354, l355, l356, l357,
+        l358, l359, l360, l361, l362, l363, l364, l365, l366, l367,
+        l368, l369, l370, l371, l372, l373, l374, l375, l376, l377,
+        l378, l379, l380, l381, l382, l383, l384, l385, l386, l387,
+        l388, l389, l390, l391, l392, l393, l394, l395, l396, l397,
+        l398, l399, l400, l401, l402, l403, l404, l405, l406, l407,
+        l408, l409, l410, l411, l412, l413, l414, l415, l416, l417,
+        l418, l419, l420, l421, l422, l423, l424, l425, l426, l427,
+        l428, l429, l430, l431, l432, l433, l434, l435, l436, l437,
+        l438, l439, l440, l441, l442, l443, l444, l445, l446, l447,
+        l448, l449, l450, l451, l452, l453, l454, l455, l456, l457,
+        l458, l459, l460, l461, l462, l463, l464, l465, l466, l467,
+        l468, l469, l470, l471, l472, l473, l474, l475, l476, l477,
+        l478, l479, l480, l481, l482, l483, l484, l485, l486, l487,
+        l488, l489, l490, l491, l492, l493, l494, l495, l496, l497,
+        l498, l499, l500, l501, l502, l503, l504, l505, l506, l507,
+        l508, l509, l510, l511;
+
+        count++;
+        m2();
+    }
+
+    static Object m3(boolean overflow_stack, boolean deopt) {
+        if (overflow_stack) {
+            m2();
+            return null;
+        }
+        Object o = m1(deopt);
+        if (deopt) {
+            m2();
+        }
+        return o;
+    }
+
+    static public void main(String[] args) {
+        int c1;
+        // Call m2 from m3 recursively until stack overflow. Count the number of recursive calls.
+        try {
+            m3(true, false);
+        } catch(StackOverflowError soe) {
+        }
+        c1 = count;
+        // Force the compilation of m3() that will inline m1()
+        for (int i = 0; i < 20000; i++) {
+            m3(false, false);
+        }
+        count = 0;
+        // Force deoptimization of m3() in m1(), then return from m1()
+        // to m3(), call recursively m2(). If deoptimization correctly
+        // built the interpreter stack for m3()/m1() then we should be
+        // able to call m2() recursively as many times as before.
+        try {
+            m3(false, true);
+        } catch(StackOverflowError soe) {
+        }
+        if (c1 != count) {
+            System.out.println("Failed: init recursive calls: " + c1 + ". After deopt " + count);
+            System.exit(97);
+        } else {
+            System.out.println("PASSED");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8011706/Test8011706.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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 8011706
+ * @summary loop invariant code motion may move load before store to the same field
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8011706
+ *
+ */
+
+public class Test8011706 {
+    int[] array;
+
+    void m(boolean test, int[] array1, int[] array2) {
+        int i = 0;
+        if (test) {
+            array = array1;
+        } else {
+            array = array2;
+        }
+
+        while(true) {
+            int v = array[i];
+            i++;
+            if (i >= 10) return;
+        }
+    }
+
+    static public void main(String[] args) {
+        int[] new_array = new int[10];
+        Test8011706 ti = new Test8011706();
+        boolean failed = false;
+        try {
+            for (int i = 0; i < 10000; i++) {
+                ti.array = null;
+                ti.m(true, new_array, new_array);
+            }
+        } catch(NullPointerException ex) {
+            throw new RuntimeException("TEST FAILED", ex);
+        }
+        System.out.println("TEST PASSED");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/ClearMethodStateTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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 ClearMethodStateTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ClearMethodStateTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClearMethodStateTest extends CompilerWhiteBoxTest {
+    public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile() and #test()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
+        new ClearMethodStateTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        checkNotCompiled(METHOD);
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.clearMethodState(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+
+        if (!TIERED_COMPILATION) {
+            WHITE_BOX.clearMethodState(METHOD);
+            compile(COMPILE_THRESHOLD);
+            checkCompiled(METHOD);
+
+            WHITE_BOX.deoptimizeMethod(METHOD);
+            checkNotCompiled(METHOD);
+            WHITE_BOX.clearMethodState(METHOD);
+
+            if (COMPILE_THRESHOLD > 1) {
+                compile(COMPILE_THRESHOLD - 1);
+                checkNotCompiled(METHOD);
+            } else {
+               System.err.println("Warning: 'CompileThreshold' <= 1");
+            }
+
+            method();
+            checkCompiled(METHOD);
+        } else {
+            System.err.println(
+                    "Warning: part of test is not applicable in Tiered");
+        }
+    }
+}
--- a/test/compiler/whitebox/CompilerWhiteBoxTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -35,6 +35,10 @@
     protected static final Method METHOD = getMethod("method");
     protected static final int COMPILE_THRESHOLD
             = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
+    protected static final boolean BACKGROUND_COMPILATION
+            = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
+    protected static final boolean TIERED_COMPILATION
+            = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
 
     protected static Method getMethod(String name) {
         try {
@@ -45,11 +49,16 @@
         }
     }
 
-    protected static String getVMOption(String name, String defaultValue) {
+    protected static String getVMOption(String name) {
         String result;
         HotSpotDiagnosticMXBean diagnostic
                 = ManagementFactoryHelper.getDiagnosticMXBean();
         result = diagnostic.getVMOption(name).getValue();
+        return result;
+    }
+
+    protected static String getVMOption(String name, String defaultValue) {
+        String result = getVMOption(name);
         return result == null ? defaultValue : result;
     }
 
@@ -66,6 +75,7 @@
         } catch (Exception e) {
             System.out.printf("on exception '%s':", e.getMessage());
             printInfo(METHOD);
+            e.printStackTrace();
             throw new RuntimeException(e);
         }
         System.out.println("at test's end:");
@@ -73,6 +83,9 @@
     }
 
     protected static void checkNotCompiled(Method method) {
+        if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
+            throw new RuntimeException(method + " must not be in queue");
+        }
         if (WHITE_BOX.isMethodCompiled(method)) {
             throw new RuntimeException(method + " must be not compiled");
         }
@@ -100,6 +113,9 @@
 
     protected static void waitBackgroundCompilation(Method method)
             throws InterruptedException {
+        if (!BACKGROUND_COMPILATION) {
+            return;
+        }
         final Object obj = new Object();
         synchronized (obj) {
             for (int i = 0; i < 10; ++i) {
@@ -128,14 +144,18 @@
     protected abstract void test() throws Exception;
 
     protected final int compile() {
+        return compile(Math.max(COMPILE_THRESHOLD, 150000));
+    }
+
+    protected final int compile(int count) {
         int result = 0;
-        for (int i = 0; i < COMPILE_THRESHOLD; ++i) {
+        for (int i = 0; i < count; ++i) {
             result += method();
         }
+        System.out.println("method was invoked " + count + " times");
         return result;
     }
 
-
     protected int method() {
         return 42;
     }
--- a/test/compiler/whitebox/DeoptimizeAllTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/DeoptimizeAllTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -32,12 +32,12 @@
 public class DeoptimizeAllTest extends CompilerWhiteBoxTest {
 
     public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         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();
--- a/test/compiler/whitebox/DeoptimizeMethodTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/DeoptimizeMethodTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -32,12 +32,12 @@
 public class DeoptimizeMethodTest extends CompilerWhiteBoxTest {
 
     public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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 EnqueueMethodForCompilationTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build EnqueueMethodForCompilationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest {
+    public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
+        new EnqueueMethodForCompilationTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, 0);
+        if (WHITE_BOX.isMethodCompilable(METHOD, 0)) {
+          throw new RuntimeException(METHOD + " is compilable at level 0");
+        }
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, -1);
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, 5);
+        if (!WHITE_BOX.isMethodCompilable(METHOD, 5)) {
+          checkNotCompiled(METHOD);
+          compile();
+          checkCompiled(METHOD);
+        } else {
+          checkCompiled(METHOD);
+        }
+
+        int compLevel = WHITE_BOX.getMethodCompilationLevel(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, compLevel);
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+    }
+}
--- a/test/compiler/whitebox/IsMethodCompilableTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/IsMethodCompilableTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -44,6 +44,8 @@
     }
 
     public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new IsMethodCompilableTest().runTest();
     }
 
@@ -58,28 +60,47 @@
                     "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf");
             return;
         }
-        // to prevent inlining #method into #compile()
-        WHITE_BOX.setDontInlineMethod(METHOD, true);
-        boolean madeNotCompilable = false;
+
+        // deoptimze 'PerMethodRecompilationCutoff' times and clear state
+        for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) {
+            compileAndDeoptimaze();
+        }
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " is not compilable after "
+                    + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations");
+        }
+        WHITE_BOX.clearMethodState(METHOD);
 
-        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;
-            }
+        // deoptimze 'PerMethodRecompilationCutoff' + 1 times
+        long i;
+        for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF
+                && WHITE_BOX.isMethodCompilable(METHOD); ++i) {
+            compileAndDeoptimaze();
         }
-        if (!madeNotCompilable) {
+        if (i != PER_METHOD_RECOMPILATION_CUTOFF) {
+           throw new RuntimeException(METHOD + " is not compilable after "
+                   + i + " iterations, but must only after "
+                   + PER_METHOD_RECOMPILATION_CUTOFF);
+        }
+        if (WHITE_BOX.isMethodCompilable(METHOD)) {
             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");
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.clearMethodState(METHOD);
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD
+                    + " is compilable after clearMethodState()");
         }
+        compile();
+        checkCompiled(METHOD);
+    }
+
+    private void compileAndDeoptimaze() throws Exception {
+        compile();
+        waitBackgroundCompilation(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
     }
 }
--- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -32,6 +32,8 @@
 public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
 
     public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new MakeMethodNotCompilableTest().runTest();
     }
 
@@ -44,9 +46,6 @@
             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");
--- a/test/compiler/whitebox/SetDontInlineMethodTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/compiler/whitebox/SetDontInlineMethodTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,23 +36,23 @@
     }
 
     protected void test() throws Exception {
-        if (WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+        if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
             throw new RuntimeException("on start " + METHOD
                     + " must be inlineable");
         }
-        if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+        if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
             throw new RuntimeException("after first change to true " + METHOD
                     + " must be not inlineable");
         }
-        if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (!WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
             throw new RuntimeException("after second change to true " + METHOD
                     + " must be still not inlineable");
         }
-        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
             throw new RuntimeException("after first change to false" + METHOD
                     + " must be inlineable");
         }
-        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (WHITE_BOX.testSetDontInlineMethod(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/compiler/whitebox/SetForceInlineMethodTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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 SetForceInlineMethodTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SetForceInlineMethodTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class SetForceInlineMethodTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new SetForceInlineMethodTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, true)) {
+            throw new RuntimeException("on start " + METHOD
+                    + " must be not force inlineable");
+        }
+        if (!WHITE_BOX.testSetForceInlineMethod(METHOD, true)) {
+            throw new RuntimeException("after first change to true " + METHOD
+                    + " must be force inlineable");
+        }
+        if (!WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to true " + METHOD
+                    + " must be still force inlineable");
+        }
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after first change to false" + METHOD
+                    + " must be not force inlineable");
+        }
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to false " + METHOD
+                    + " must be not force inlineable");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/6941923/Test6941923.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test Test6941923.java
+ * @bug 6941923
+ * @summary test flags for gc log rotation
+ * @library /testlibrary
+ * @run main/othervm/timeout=600 Test6941923
+ *
+ */
+import com.oracle.java.testlibrary.*;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class GCLoggingGenerator {
+
+    public static void main(String[] args) throws Exception {
+
+        long sizeOfLog = Long.parseLong(args[0]);
+        long lines = sizeOfLog / 80;
+        // full.GC generates ad least 1-line which is not shorter then 80 chars
+        // for some GC 2 shorter lines are generated
+        for (long i = 0; i < lines; i++) {
+            System.gc();
+        }
+    }
+}
+
+public class Test6941923 {
+
+    static final File currentDirectory = new File(".");
+    static final String logFileName = "test.log";
+    static final int logFileSizeK = 16;
+    static FilenameFilter logFilter = new FilenameFilter() {
+        @Override
+        public boolean accept(File dir, String name) {
+            return name.startsWith(logFileName);
+        }
+    };
+
+    public static void cleanLogs() {
+        for (File log : currentDirectory.listFiles(logFilter)) {
+            if (!log.delete()) {
+                throw new Error("Unable to delete " + log.getAbsolutePath());
+            }
+        }
+    }
+
+    public static void runTest(int numberOfFiles) throws Exception {
+
+        ArrayList<String> args = new ArrayList();
+        String[] logOpts = new String[]{
+            "-cp", System.getProperty("java.class.path"),
+            "-Xloggc:" + logFileName,
+            "-XX:-DisableExplicitGC", // to sure that System.gc() works
+            "-XX:+PrintGC", "-XX:+PrintGCDetails", "-XX:+UseGCLogFileRotation",
+            "-XX:NumberOfGCLogFiles=" + numberOfFiles,
+            "-XX:GCLogFileSize=" + logFileSizeK + "K", "-Xmx128M"};
+        // System.getProperty("test.java.opts") is '' if no options is set
+        // need to skip such empty
+        String[] externalVMopts = System.getProperty("test.java.opts").length() == 0
+                ? new String[0]
+                : System.getProperty("test.java.opts").split(" ");
+        args.addAll(Arrays.asList(externalVMopts));
+        args.addAll(Arrays.asList(logOpts));
+        args.add(GCLoggingGenerator.class.getName());
+        args.add(String.valueOf(numberOfFiles * logFileSizeK * 1024));
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0]));
+        pb.redirectErrorStream(true);
+        pb.redirectOutput(new File(GCLoggingGenerator.class.getName() + ".log"));
+        Process process = pb.start();
+        int result = process.waitFor();
+        if (result != 0) {
+            throw new Error("Unexpected exit code = " + result);
+        }
+        File[] logs = currentDirectory.listFiles(logFilter);
+        int smallFilesNumber = 0;
+        for (File log : logs) {
+            if (log.length() < logFileSizeK * 1024) {
+                smallFilesNumber++;
+            }
+        }
+        if (logs.length != numberOfFiles) {
+            throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles);
+        }
+        if (smallFilesNumber > 1) {
+            throw new Error("There should maximum one log with size < " + logFileSizeK + "K");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        cleanLogs();
+        runTest(1);
+        cleanLogs();
+        runTest(3);
+        cleanLogs();
+    }
+}
--- a/test/gc/6941923/test6941923.sh	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-##
-## @test @(#)test6941923.sh
-## @bug 6941923 
-## @summary test new added flags for gc log rotation 
-## @author yqi 
-## @run shell test6941923.sh
-##
-
-## skip on windows
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_* | CYGWIN_* )
-    echo "Test skipped for Windows"
-    exit 0 
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-if [ "${JAVA_HOME}" = "" ]
-then
-  echo "JAVA_HOME not set"
-  exit 0
-fi
-
-$JAVA_HOME/bin/java ${TESTVMOPTS} -version > $NULL 2>&1
-
-if [ $? != 0 ]; then
-  echo "Wrong JAVA_HOME? JAVA_HOME: $JAVA_HOME"
-  exit $?
-fi
-
-# create a small test case
-testname="Test"
-if [ -e ${testname}.java ]; then
-  rm -rf ${testname}.*
-fi
-
-cat >> ${testname}.java << __EOF__
-import java.util.Vector;
-
-public class Test implements Runnable
-{
-  private boolean _should_stop = false;
-
-  public static void main(String[] args) throws Exception {
-
-    long limit = Long.parseLong(args[0]) * 60L * 1000L;   // minutes
-    Test t = new Test();
-    t.set_stop(false);
-    Thread thr = new Thread(t);
-    thr.start();
-
-    long time1 = System.currentTimeMillis();
-    long time2 = System.currentTimeMillis();
-    while (time2 - time1 < limit) {
-      try {
-        Thread.sleep(2000); // 2 seconds
-      }
-      catch(Exception e) {}
-      time2 = System.currentTimeMillis();
-      System.out.print("\r... " + (time2 - time1)/1000 + " seconds");
-    }
-    System.out.println();
-    t.set_stop(true);
-  }
-  public void set_stop(boolean value) { _should_stop = value; }
-  public void run() {
-    int cap = 20000;
-    int fix_size = 2048;
-    int loop = 0;
-    Vector< byte[] > v = new Vector< byte[] >(cap);
-    while(!_should_stop) {
-      byte[] g = new byte[fix_size];
-      v.add(g);
-      loop++;
-      if (loop > cap) {
-         v = null;
-         cap *= 2;
-         if (cap > 80000) cap = 80000;
-         v = new Vector< byte[] >(cap);
-      }
-    }
-  }
-}
-__EOF__
-
-msgsuccess="succeeded"
-msgfail="failed"
-gclogsize="16K"
-filesize=$((16*1024))
-$JAVA_HOME/bin/javac ${testname}.java > $NULL 2>&1
-
-if [ $? != 0 ]; then
-  echo "$JAVA_HOME/bin/javac ${testname}.java $fail"
-  exit -1
-fi
-
-# test for 2 minutes, it will complete circulation of gc log rotation
-tts=2
-logfile="test.log"
-hotspotlog="hotspot.log"
-
-if [ -e $logfile  ]; then
-  rm -rf $logfile
-fi
-
-#also delete $hotspotlog if it exists
-if [ -f $hotspotlog ]; then 
-  rm -rf $hotspotlog
-fi
-
-options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize"
-echo "Test gc log rotation in same file, wait for $tts minutes ...."
-$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts
-if [ $? != 0 ]; then
-  echo "$msgfail"
-  exit -1
-fi
-
-# rotation file will be $logfile.0 
-if [ -f $logfile.0 ]; then
-  outfilesize=`ls -l $logfile.0 | awk '{print $5 }'`
-  if [ $((outfilesize)) -ge $((filesize)) ]; then
-    echo $msgsuccess
-  else
-    echo $msgfail
-  fi
-else 
-  echo $msgfail
-  exit -1
-fi
-
-# delete log file 
-rm -rf $logfile.0
-if [ -f $hotspotlog ]; then
-  rm -rf $hotspotlog
-fi
-
-#multiple log files
-numoffiles=3
-options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize"
-echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...."
-$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts
-if [ $? != 0 ]; then
-  echo "$msgfail"
-  exit -1
-fi
-
-atleast=0    # at least size of numoffile-1 files >= $gclogsize
-tk=0
-while [ $(($tk)) -lt $(($numoffiles)) ]
-do
-  if [ -f $logfile.$tk ]; then
-    outfilesize=`ls -l $logfile.$tk | awk '{ print $5 }'`
-    if [ $(($outfilesize)) -ge $(($filesize)) ]; then
-      atleast=$((atleast+1))
-    fi
-  fi
-  tk=$((tk+1))
-done
-
-rm -rf $logfile.*
-rm -rf $testname.*
-rm -rf $hotspotlog
-
-if [ $(($atleast)) -ge $(($numoffiles-1)) ]; then
-  echo $msgsuccess
-else
-  echo $msgfail
-  exit -1
-fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/TestVerifyDuringStartup.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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 TestVerifyDuringStartup.java
+ * @key gc
+ * @bug 8010463
+ * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestVerifyDuringStartup {
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb =
+      ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
+                                            "-XX:-UseTLAB",
+                                            "-XX:+UnlockDiagnosticVMOptions",
+                                            "-XX:+VerifyDuringStartup", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("[Verifying");
+    output.shouldHaveExitValue(0);
+  }
+}
--- a/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java	Mon Apr 15 08:51:19 2013 +0200
@@ -39,8 +39,10 @@
     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);
+        JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+                                              .addToolArg("-heap")
+                                              .addToolArg(pid);
+        ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
 
         File out = new File("ClassMetaspaceSizeInJmapHeap.stdout.txt");
         pb.redirectOutput(out);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/metaspace/G1AddMetaspaceDependency.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,123 @@
+/*
+ * 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 G1AddMetaspaceDependency
+ * @bug 8010196
+ * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor
+ * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency
+ */
+
+import java.io.InputStream;
+
+public class G1AddMetaspaceDependency {
+
+  static byte[] getClassBytes(String name) {
+    byte[] b = null;
+    try (InputStream is = ClassLoader.getSystemResourceAsStream(name)) {
+      byte[] tmp = new byte[is.available()];
+      is.read(tmp);
+      b = tmp;
+    } finally {
+      if (b == null) {
+        throw new RuntimeException("Unable to load class file");
+      }
+      return b;
+    }
+  }
+
+  static final String a_name = G1AddMetaspaceDependency.class.getName() + "$A";
+  static final String b_name = G1AddMetaspaceDependency.class.getName() + "$B";
+
+  public static void main(String... args) throws Exception {
+    final byte[] a_bytes = getClassBytes(a_name + ".class");
+    final byte[] b_bytes = getClassBytes(b_name + ".class");
+
+    for (int i = 0; i < 1000; i += 1) {
+      runTest(a_bytes, b_bytes);
+    }
+  }
+
+  static class Loader extends ClassLoader {
+    private final String myClass;
+    private final byte[] myBytes;
+    private final String friendClass;
+    private final ClassLoader friendLoader;
+
+    Loader(String myClass, byte[] myBytes,
+           String friendClass, ClassLoader friendLoader) {
+      this.myClass = myClass;
+      this.myBytes = myBytes;
+      this.friendClass = friendClass;
+      this.friendLoader = friendLoader;
+    }
+
+    Loader(String myClass, byte[] myBytes) {
+      this(myClass, myBytes, null, null);
+    }
+
+    @Override
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+      Class<?> c = findLoadedClass(name);
+      if (c != null) {
+        return c;
+      }
+
+      if (name.equals(friendClass)) {
+        return friendLoader.loadClass(name);
+      }
+
+      if (name.equals(myClass)) {
+        c = defineClass(name, myBytes, 0, myBytes.length);
+        resolveClass(c);
+        return c;
+      }
+
+      return findSystemClass(name);
+    }
+
+  }
+
+  private static void runTest(final byte[] a_bytes, final byte[] b_bytes) throws Exception {
+    Loader a_loader = new Loader(a_name, a_bytes);
+    Loader b_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader c_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader d_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader e_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+
+    byte[] b = new byte[20 * 2 << 20];
+    Class<?> c;
+    c = b_loader.loadClass(b_name);
+    c = c_loader.loadClass(b_name);
+    c = d_loader.loadClass(b_name);
+    c = e_loader.loadClass(b_name);
+    c = f_loader.loadClass(b_name);
+    c = g_loader.loadClass(b_name);
+  }
+  public class A {
+  }
+  class B extends A {
+  }
+}
--- a/test/runtime/6626217/Test6626217.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/6626217/Test6626217.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -27,78 +27,29 @@
 # @summary Loader-constraint table allows arrays instead of only the base-classes
 # @run shell Test6626217.sh
 #
-
+## some tests require path to find test source dir
 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
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    RM=/bin/rm
-    CP=/bin/cp
-    MV=/bin/mv
-    ;;
-  Windows_* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    RM=rm
-    CP=cp
-    MV=mv
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    RM=rm
-    CP=cp
-    MV=mv
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-JEMMYPATH=${CPAPPEND}
-CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
-
-THIS_DIR=`pwd`
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 JAVA=${TESTJAVA}${FS}bin${FS}java
-JAVAC=${TESTJAVA}${FS}bin${FS}javac
-
-${JAVA} ${TESTVMOPTS} -version
+JAVAC=${COMPILEJAVA}${FS}bin${FS}javac
 
 # Current directory is scratch directory, copy all the test source there
 # (for the subsequent moves to work).
-${CP} ${TESTSRC}${FS}*  ${THIS_DIR}
+${CP} ${TESTSRC}${FS}* ${THIS_DIR}
 
 # A Clean Compile: this line will probably fail within jtreg as have a clean dir:
 ${RM} -f *.class *.impl many_loader.java
 
 # Compile all the usual suspects, including the default 'many_loader'
 ${CP} many_loader1.java.foo many_loader.java
-${JAVAC} -source 1.4 -target 1.4 -Xlint *.java
+${JAVAC} ${TESTJAVACOPTS} -source 1.4 -target 1.4 -Xlint *.java
 
 # Rename the class files, so the custom loader (and not the system loader) will find it
 ${MV} from_loader2.class from_loader2.impl2
@@ -106,7 +57,7 @@
 # Compile the next version of 'many_loader'
 ${MV} many_loader.class many_loader.impl1
 ${CP} many_loader2.java.foo many_loader.java
-${JAVAC} -source 1.4 -target 1.4 -Xlint many_loader.java
+${JAVAC} ${TESTJAVACOPTS} -source 1.4 -target 1.4 -Xlint many_loader.java
 
 # Rename the class file, so the custom loader (and not the system loader) will find it
 ${MV} many_loader.class many_loader.impl2
--- a/test/runtime/6878713/Test6878713.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/6878713/Test6878713.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -1,71 +1,137 @@
 #!/bin/sh
 
+# 
+#  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.
+# 
+
+ 
+
 ##
 ## @test
 ## @bug 6878713
+## @bug 7030610
+## @bug 7037122
+## @bug 7123945
 ## @summary Verifier heap corruption, relating to backward jsrs
-## @run shell/timeout=120 Test6878713.sh
+## @run shell Test6878713.sh
 ##
-
+## some tests require path to find test source dir
 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."
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
+TARGET_CLASS=OOMCrashClass1960_2
+
+echo "INFO: extracting the target class."
+${COMPILEJAVA}${FS}bin${FS}jar xvf \
+    ${TESTSRC}${FS}testcase.jar ${TARGET_CLASS}.class
+
+# remove any hs_err_pid that might exist here
+rm -f hs_err_pid*.log
+
+echo "INFO: checking for 32-bit versus 64-bit VM."
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version 2>&1 \
+    | grep "64-Bit [^ ][^ ]* VM" > /dev/null 2>&1
+status="$?"
+if [ "$status" = 0 ]; then
+    echo "INFO: testing a 64-bit VM."
+    is_64_bit=true
+else
+    echo "INFO: testing a 32-bit VM."
 fi
 
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
+if [ "$is_64_bit" = true ]; then
+    # limit is 768MB in 8-byte words (1024 * 1024 * 768 / 8) == 100663296
+    MALLOC_MAX=100663296
+else
+    # limit is 768MB in 4-byte words (1024 * 1024 * 768 / 4) == 201326592
+    MALLOC_MAX=201326592
+fi
+echo "INFO: MALLOC_MAX=$MALLOC_MAX"
+
+echo "INFO: executing the target class."
+# -XX:+PrintCommandLineFlags for debugging purposes
+# -XX:+IgnoreUnrecognizedVMOptions so test will run on a VM without
+#     the new -XX:MallocMaxTestWords option
+# -XX:+UnlockDiagnosticVMOptions so we can use -XX:MallocMaxTestWords
+# -XX:MallocMaxTestWords limits malloc to $MALLOC_MAX
+${TESTJAVA}${FS}bin${FS}java \
+    -XX:+PrintCommandLineFlags \
+    -XX:+IgnoreUnrecognizedVMOptions \
+    -XX:+UnlockDiagnosticVMOptions \
+    -XX:MallocMaxTestWords=$MALLOC_MAX \
+    ${TESTVMOPTS} ${TARGET_CLASS} > test.out 2>&1
+
+echo "INFO: begin contents of test.out:"
+cat test.out
+echo "INFO: end contents of test.out."
 
-JEMMYPATH=${CPAPPEND}
-CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
-
-THIS_DIR=`pwd`
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
-
-${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar
+echo "INFO: checking for memory allocation error message."
+# We are looking for this specific memory allocation failure mesg so
+# we know we exercised the right allocation path with the test class:
+MESG1="Native memory allocation (malloc) failed to allocate 25696531[0-9][0-9] bytes"
+grep "$MESG1" test.out
+status="$?"
+if [ "$status" = 0 ]; then
+    echo "INFO: found expected memory allocation error message."
+else
+    echo "INFO: did not find expected memory allocation error message."
 
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass1960_2 > test.out 2>&1
+    # If we didn't find MESG1 above, then there are several scenarios:
+    # 1) -XX:MallocMaxTestWords is not supported by the current VM and we
+    #    didn't fail TARGET_CLASS's memory allocation attempt; instead
+    #    we failed to find TARGET_CLASS's main() method. The TARGET_CLASS
+    #    is designed to provoke a memory allocation failure during class
+    #    loading; we actually don't care about running the class which is
+    #    why it doesn't have a main() method.
+    # 2) we failed a memory allocation, but not the one we were looking
+    #    so it might be that TARGET_CLASS no longer tickles the same
+    #    memory allocation code path
+    # 3) TARGET_CLASS reproduces the failure mode (SIGSEGV) fixed by
+    #    6878713 because the test is running on a pre-fix VM.
+    echo "INFO: checking for no main() method message."
+    MESG2="Error: Main method not found in class"
+    grep "$MESG2" test.out
+    status="$?"
+    if [ "$status" = 0 ]; then
+        echo "INFO: found no main() method message."
+    else
+        echo "FAIL: did not find no main() method message."
+        # status is non-zero for exit below
 
-if [ -s core -o -s "hs_*.log" ]
-then
-    cat hs*.log
-    echo "Test Failed"
-    exit 1
-else
-    echo "Test Passed"
-    exit 0
+        if [ -s hs_err_pid*.log ]; then
+            echo "INFO: begin contents of hs_err_pid file:"
+            cat hs_err_pid*.log
+            echo "INFO: end contents of hs_err_pid file."
+        fi
+    fi
 fi
+
+if [ "$status" = 0 ]; then
+    echo "PASS: test found one of the expected messages."
+fi
+exit "$status"
--- a/test/runtime/6929067/Test6929067.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/6929067/Test6929067.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -7,18 +7,15 @@
 ## @compile T.java
 ## @run shell Test6929067.sh
 ##
-
+set -x
 if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
+then
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 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
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 # set platform-dependent variables
 OS=`uname -s`
@@ -107,7 +104,7 @@
 fi
 
 
-LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${ARCH}/${VMTYPE}:/usr/lib:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE}:/usr/lib:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
 
 cp ${TESTSRC}${FS}invoke.c .
@@ -115,15 +112,16 @@
 # Copy the result of our @compile action:
 cp ${TESTCLASSES}${FS}T.class .
 
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
-
 echo "Architecture: ${ARCH}"
 echo "Compilation flag: ${COMP_FLAG}"
 echo "VM type: ${VMTYPE}"
+# Note pthread may not be found thus invoke creation will fail to be created.
+# Check to ensure you have a /usr/lib/libpthread.so if you don't please look
+# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation.
 
 gcc -DLINUX ${COMP_FLAG} -o invoke \
-  -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \
-  -L${TESTJAVA}/jre/lib/${ARCH}/${VMTYPE} \
+  -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \
+  -L${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE} \
   -ljvm -lpthread invoke.c
 
 ./invoke
--- a/test/runtime/7020373/Test7020373.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7020373/Test7020373.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -10,55 +10,15 @@
 ##
 
 if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
+then
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 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
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-JEMMYPATH=${CPAPPEND}
-CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
-
-THIS_DIR=`pwd`
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
-
-${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar
+${COMPILEJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar
 
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass4000_1 > test.out 2>&1
 
--- a/test/runtime/7051189/Xchecksig.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7051189/Xchecksig.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -29,34 +29,22 @@
 #
 
 if [ "${TESTSRC}" = "" ]
-  then TESTSRC=.
+then
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
-
-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
-
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 OS=`uname -s`
 case "$OS" in
-  SunOS | Linux | Darwin )
-    FS="/"
-    ;;
   Windows_* | CYGWIN_* )
     printf "Not testing libjsig.so on Windows. PASSED.\n "
     exit 0
     ;;
-  * )
-    printf "Not testing libjsig.so on unrecognised system. PASSED.\n "
-    exit 0
-    ;;
 esac
 
-
 JAVA=${TESTJAVA}${FS}bin${FS}java
 
 # LD_PRELOAD arch needs to match the binary we run, so run the java
@@ -97,7 +85,7 @@
   ;; 
 esac
 
-LIBJSIG=${TESTJAVA}${FS}jre${FS}lib${FS}${ARCH}${FS}libjsig.so
+LIBJSIG=${COMPILEJAVA}${FS}jre${FS}lib${FS}${ARCH}${FS}libjsig.so
 
 # If libjsig and binary do not match, skip test.
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7107135/Test.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG.  All Rights Reserved.
+ * 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.
+ */
+
+class Test {
+
+    static boolean loadLib(String libName){
+        try {
+            System.loadLibrary(libName);
+            System.out.println("Loaded library "+ libName + ".");
+            return true;
+        } catch (SecurityException e) {
+            System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+        } catch (UnsatisfiedLinkError e) {
+            System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+        }
+        return false;
+    }
+
+    public static int counter = 1;
+
+    static int Runner() {
+        counter = counter * -1;
+        int i = counter;
+        if(counter < 2) counter += Runner();
+        return i;
+    }
+
+    public static int run() {
+        try{
+            Runner();
+        } catch (StackOverflowError e) {
+            System.out.println("Caught stack overflow error.");
+            return 0;
+        } catch (OutOfMemoryError e) {
+            return 0;
+        }
+        return 2;
+    }
+
+    public static void main(String argv[]) {
+        loadLib(argv[0]);
+        System.exit(run());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7107135/Test7107135.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+#
+#  Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+#  Copyright (c) 2011 SAP AG.  All Rights Reserved.
+#  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 Test7107135.sh
+## @bug 7107135
+## @summary Stack guard pages lost after loading library with executable stack.
+## @run shell Test7107135.sh
+##
+
+if [ "${TESTSRC}" = "" ]
+then
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
+fi
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Linux)
+    echo "Testing on Linux"
+    ;;
+  *)
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    echo "Test passed; only valid for Linux"
+    exit 0;
+    ;;
+esac
+
+ARCH=`uname -m`
+
+THIS_DIR=.
+
+cp ${TESTSRC}${FS}*.java ${THIS_DIR}
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+gcc -fPIC -shared -c -o test.o -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux ${TESTSRC}${FS}test.c
+ld -shared -z   execstack -o libtest-rwx.so test.o
+ld -shared -z noexecstack -o libtest-rw.so  test.o
+
+
+LD_LIBRARY_PATH=${THIS_DIR}
+echo   LD_LIBRARY_PATH = ${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+# This should not fail.
+echo Check testprogram. Expected to pass:
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+
+echo
+echo Test changing of stack protection:
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rwx
+
+if [ "$?" == "0" ]
+then
+  echo
+  echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx
+  ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx
+fi
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7107135/TestMT.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG.  All Rights Reserved.
+ * 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.
+ */
+
+class TestMT {
+
+    static boolean loadLib(String libName) {
+        try {
+            System.loadLibrary(libName);
+            System.out.println("Loaded library "+ libName + ".");
+            return true;
+        } catch (SecurityException e) {
+            System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+        } catch (UnsatisfiedLinkError e) {
+            System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+        }
+        return false;
+    }
+
+    public static int counter        = 1;
+    static int Runner() {
+        counter = counter * -1;
+        int i = counter;
+        if (counter < 2) counter += Runner();
+        return i;
+    }
+
+    public static int run(String msg) {
+        try {
+            Runner();
+        } catch (StackOverflowError e) {
+            System.out.println(msg + " caught stack overflow error.");
+            return 0;
+        } catch (OutOfMemoryError e) {
+            return 0;
+        }
+        return 2;
+    }
+
+    public static void main(String argv[]) {
+        try {
+            for (int i = 0; i < 20; i++) {
+                Thread t = new DoStackOverflow("SpawnedThread " + i);
+                t.start();
+            }
+            run("Main thread");
+            loadLib("test-rwx");
+            run("Main thread");
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+    }
+
+    static class DoStackOverflow extends Thread {
+        public DoStackOverflow(String name) {
+            super(name);
+        }
+        public void run() {
+            for (int i = 0; i < 10; ++i) {
+                TestMT.run(getName());
+                yield();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7107135/test.c	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG.  All Rights Reserved.
+ * 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "jni.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jint JNICALL Java_Test_someMethod(JNIEnv *env, jobject mainObject) {
+  return 3;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/runtime/7110720/Test7110720.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7110720/Test7110720.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -12,22 +12,13 @@
 #
 
 if [ "${TESTSRC}" = "" ]
-  then TESTSRC=.
+then
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 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
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 # Jtreg sets TESTVMOPTS which may include -d64 which is
 # required to test a 64-bit JVM on some platforms.
--- a/test/runtime/7116786/Test7116786.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7116786/Test7116786.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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
@@ -338,9 +338,12 @@
                  "invalid constant pool index in ldc",
                  "Invalid index in ldc"),
 
-        new Case("case58", "verifier.cpp", true, "verify_switch",
+        /* No longer a valid test case for bytecode version >= 51. Nonzero
+         * padding bytes are permitted with lookupswitch and tableswitch
+         * bytecodes as of JVMS 3d edition */
+        new Case("case58", "verifier.cpp", false, "verify_switch",
                  "bad switch padding",
-                 "Nonzero padding byte in lookswitch or tableswitch"),
+                 "Nonzero padding byte in lookupswitch or tableswitch"),
 
         new Case("case59", "verifier.cpp", true, "verify_switch",
                  "tableswitch low is greater than high",
--- a/test/runtime/7158804/Test7158804.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7158804/Test7158804.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -10,13 +10,14 @@
 ## @summary Improve config file parsing
 ## @run shell Test7158804.sh
 ##
-
-if [ "${TESTJAVA}" = "" ]
+if [ "${TESTSRC}" = "" ]
 then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
-echo "TESTJAVA=${TESTJAVA}"
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 rm -f .hotspotrc
 echo -XX:+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >.hotspotrc
--- a/test/runtime/7162488/Test7162488.sh	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/7162488/Test7162488.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -29,27 +29,13 @@
 #
 
 if [ "${TESTSRC}" = "" ]
-  then TESTSRC=.
-fi
-
-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"
+  TESTSRC=${PWD}
+  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
 fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Windows_* )
-    FS="\\"
-    ;;
-  * )
-    FS="/"
-    ;;
-esac
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
 
 JAVA=${TESTJAVA}${FS}bin${FS}java
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/8003985/Test8003985.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,302 @@
+/*
+ * 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.BufferedReader;
+import java.io.InputStreamReader;
+import java.lang.Class;
+import java.lang.String;
+import java.lang.System;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CyclicBarrier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import sun.misc.Unsafe;
+import sun.misc.Contended;
+
+/*
+ * @test
+ * @bug     8003985
+ * @summary Support Contended Annotation - JEP 142
+ *
+ * @run main/othervm -XX:-RestrictContended Test8003985
+ */
+public class Test8003985 {
+
+    private static final Unsafe U;
+    private static int ADDRESS_SIZE;
+    private static int HEADER_SIZE;
+
+    static {
+        // steal Unsafe
+        try {
+            Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
+            unsafe.setAccessible(true);
+            U = (Unsafe) unsafe.get(null);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+
+        // When running with CompressedOops on 64-bit platform, the address size
+        // reported by Unsafe is still 8, while the real reference fields are 4 bytes long.
+        // Try to guess the reference field size with this naive trick.
+        try {
+            long off1 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj1"));
+            long off2 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj2"));
+            ADDRESS_SIZE = (int) Math.abs(off2 - off1);
+            HEADER_SIZE = (int) Math.min(off1, off2);
+        } catch (NoSuchFieldException e) {
+            ADDRESS_SIZE = -1;
+        }
+    }
+
+    static class CompressedOopsClass {
+        public Object obj1;
+        public Object obj2;
+    }
+
+    public static boolean arePaddedPairwise(Class klass, String field1, String field2) throws Exception {
+        Field f1 = klass.getDeclaredField(field1);
+        Field f2 = klass.getDeclaredField(field2);
+
+        if (isStatic(f1) != isStatic(f2)) {
+            return true; // these guys are in naturally disjoint locations
+        }
+
+        int diff = offset(f1) - offset(f2);
+        if (diff < 0) {
+            // f1 is first
+            return (offset(f2) - (offset(f1) + getSize(f1))) > 64;
+        } else {
+            // f2 is first
+            return (offset(f1) - (offset(f2) + getSize(f2))) > 64;
+        }
+    }
+
+    public static boolean isPadded(Class klass, String field1) throws Exception {
+        Field f1 = klass.getDeclaredField(field1);
+
+        if (isStatic(f1)) {
+            return offset(f1) > 128 + 64;
+        }
+
+        return offset(f1) > 64;
+    }
+
+    public static boolean sameLayout(Class klass1, Class klass2) throws Exception {
+        for (Field f1 : klass1.getDeclaredFields()) {
+            Field f2 = klass2.getDeclaredField(f1.getName());
+            if (offset(f1) != offset(f2)) {
+                return false;
+            }
+        }
+
+        for (Field f2 : klass1.getDeclaredFields()) {
+            Field f1 = klass2.getDeclaredField(f2.getName());
+            if (offset(f1) != offset(f2)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static boolean isStatic(Field field) {
+        return Modifier.isStatic(field.getModifiers());
+    }
+
+    public static int offset(Field field) {
+        if (isStatic(field)) {
+            return (int) U.staticFieldOffset(field);
+        } else {
+            return (int) U.objectFieldOffset(field);
+        }
+    }
+
+    public static int getSize(Field field) {
+        Class type = field.getType();
+        if (type == byte.class)    { return 1; }
+        if (type == boolean.class) { return 1; }
+        if (type == short.class)   { return 2; }
+        if (type == char.class)    { return 2; }
+        if (type == int.class)     { return 4; }
+        if (type == float.class)   { return 4; }
+        if (type == long.class)    { return 8; }
+        if (type == double.class)  { return 8; }
+        return ADDRESS_SIZE;
+    }
+
+    public static void main(String[] args) throws Exception {
+        boolean endResult = true;
+
+        // --------------- INSTANCE FIELDS ---------------------
+
+        if (arePaddedPairwise(Test1.class, "int1", "int2") ||
+                isPadded(Test1.class, "int1") ||
+                isPadded(Test1.class, "int2")) {
+            System.err.println("Test1 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test2.class, "int1", "int2") ||
+                !isPadded(Test2.class, "int1") ||
+                isPadded(Test2.class, "int2")) {
+            System.err.println("Test2 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test3.class, "int1", "int2") ||
+                !isPadded(Test3.class, "int1") ||
+                !isPadded(Test3.class, "int2")) {
+            System.err.println("Test3 failed");
+            endResult &= false;
+        }
+
+        if (arePaddedPairwise(Test4.class, "int1", "int2") ||
+                !isPadded(Test4.class, "int1") ||
+                !isPadded(Test4.class, "int2")) {
+            System.err.println("Test4 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test5.class, "int1", "int2") ||
+                !isPadded(Test5.class, "int1") ||
+                !isPadded(Test5.class, "int2")) {
+            System.err.println("Test5 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test6.class, "int1", "int2") ||
+                !isPadded(Test6.class, "int1") ||
+                !isPadded(Test6.class, "int2")) {
+            System.err.println("Test6 failed");
+            endResult &= false;
+        }
+
+        if (arePaddedPairwise(Test7.class, "int1", "int2") ||
+                !isPadded(Test7.class, "int1") ||
+                !isPadded(Test7.class, "int2")) {
+            System.err.println("Test7 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test8.class, "int1", "int2") ||
+                !isPadded(Test8.class, "int1") ||
+                !isPadded(Test8.class, "int2")) {
+            System.err.println("Test8 failed");
+            endResult &= false;
+        }
+
+        if (!arePaddedPairwise(Test9.class, "int1", "int2") ||
+                !isPadded(Test9.class, "int1") ||
+                !isPadded(Test9.class, "int2")) {
+            System.err.println("Test9 failed");
+            endResult &= false;
+        }
+
+        if (!sameLayout(Test4.class, Test7.class)) {
+            System.err.println("Test4 and Test7 have different layouts");
+            endResult &= false;
+        }
+
+        if (!sameLayout(Test5.class, Test6.class)) {
+            System.err.println("Test5 and Test6 have different layouts");
+            endResult &= false;
+        }
+
+        if (!sameLayout(Test8.class, Test9.class)) {
+            System.err.println("Test8 and Test9 have different layouts");
+            endResult &= false;
+        }
+
+        System.out.println(endResult ? "Test PASSES" : "Test FAILS");
+        if (!endResult) {
+           throw new Error("Test failed");
+        }
+    }
+
+    // ----------------------------------- INSTANCE FIELDS -----------------------------------------
+
+    // naturally packed
+    public static class Test1 {
+                                 private int int1;
+                                 private int int2;
+    }
+
+    // int1 is padded
+    public static class Test2 {
+        @Contended               private int int1;
+                                 private int int2;
+    }
+
+    // both fields are padded
+    public static class Test3 {
+        @Contended               private int int1;
+        @Contended               private int int2;
+    }
+
+    // fields are padded in the singular group
+    public static class Test4 {
+        @Contended("sameGroup")  private int int1;
+        @Contended("sameGroup")  private int int2;
+    }
+
+    // fields are padded in disjoint groups
+    public static class Test5 {
+        @Contended("diffGroup1") private int int1;
+        @Contended("diffGroup2") private int int2;
+    }
+
+    // fields are padded in disjoint groups
+    public static class Test6 {
+        @Contended               private int int1;
+        @Contended("diffGroup2") private int int2;
+    }
+
+    // fields are padded in the singular group
+    @Contended
+    public static class Test7 {
+                                 private int int1;
+                                 private int int2;
+    }
+
+    // all fields are padded as the group, and one field is padded specifically
+    @Contended
+    public static class Test8 {
+        @Contended               private int int1;
+                                 private int int2;
+    }
+
+    // all fields are padded as the group, and one field is padded specifically
+    @Contended
+    public static class Test9 {
+        @Contended("group")      private int int1;
+                                 private int int2;
+    }
+
+}
+
--- a/test/runtime/8007736/TestStaticIF.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * 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/8010389/VMThreadDlopen.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+
+import java.io.File;
+
+/*
+ * @test
+ * @key regression
+ * @bug 8010389
+ * @run main/othervm -Djava.library.path=. VMThreadDlopen
+ */
+
+public class VMThreadDlopen {
+    public static void main(String[] args) throws Exception {
+        File file = new File("libbroken.so");
+        file.createNewFile();
+        try {
+            System.loadLibrary("broken");
+        } catch (UnsatisfiedLinkError e) {
+            e.printStackTrace();
+            // expected
+        }
+    }
+}
--- a/test/runtime/CommandLine/BooleanFlagWithInvalidValue.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/CommandLine/BooleanFlagWithInvalidValue.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,17 +33,17 @@
 public class BooleanFlagWithInvalidValue {
   public static void main(String[] args) throws Exception {
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-        "-XX:+UseLargePages=8", "-version");
+        "-XX:+PrintWarnings=8", "-version");
 
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
+    output.shouldContain("Improperly specified VM option 'PrintWarnings=8'");
     output.shouldHaveExitValue(1);
 
     pb = ProcessTools.createJavaProcessBuilder(
-        "-XX:-UseLargePages=8", "-version");
+        "-XX:-PrintWarnings=8", "-version");
 
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
+    output.shouldContain("Improperly specified VM option 'PrintWarnings=8'");
     output.shouldHaveExitValue(1);
   }
 }
--- a/test/runtime/CommandLine/FlagWithInvalidValue.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/CommandLine/FlagWithInvalidValue.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,10 +33,10 @@
 public class FlagWithInvalidValue {
   public static void main(String[] args) throws Exception {
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-        "-XX:ObjectAlignmentInBytes=v", "-version");
+        "-XX:MaxRAMFraction=v", "-version");
 
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'");
+    output.shouldContain("Improperly specified VM option 'MaxRAMFraction=v'");
     output.shouldHaveExitValue(1);
   }
 }
--- a/test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java	Mon Apr 15 08:51:19 2013 +0200
@@ -33,17 +33,17 @@
 public class NonBooleanFlagWithInvalidBooleanPrefix {
   public static void main(String[] args) throws Exception {
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-        "-XX:-ObjectAlignmentInBytes=16", "-version");
+        "-XX:-MaxRAMFraction=16", "-version");
 
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
+    output.shouldContain("Unexpected +/- setting in VM option 'MaxRAMFraction=16'");
     output.shouldHaveExitValue(1);
 
     pb = ProcessTools.createJavaProcessBuilder(
-        "-XX:+ObjectAlignmentInBytes=16", "-version");
+        "-XX:+MaxRAMFraction=16", "-version");
 
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
+    output.shouldContain("Unexpected +/- setting in VM option 'MaxRAMFraction=16'");
     output.shouldHaveExitValue(1);
 
   }
--- a/test/runtime/NMT/AllocTestType.java	Thu Apr 04 11:57:04 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * 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=");
-  }
-}
--- a/test/runtime/NMT/BaselineWithParameter.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/NMT/BaselineWithParameter.java	Mon Apr 15 08:51:19 2013 +0200
@@ -43,7 +43,7 @@
 
     // Run 'jcmd <pid> VM.native_memory baseline=false'
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"});
-    pb.start();
+    pb.start().waitFor();
 
     // Run 'jcmd <pid> VM.native_memory summary=false'
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/MallocTestType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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 MallocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class MallocTestType {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Use WB API to alloc and free with the mtTest type
+    long memAlloc3 = wb.NMTMalloc(128 * 1024);
+    long memAlloc2 = wb.NMTMalloc(256 * 1024);
+    wb.NMTFree(memAlloc3);
+    long memAlloc1 = wb.NMTMalloc(512 * 1024);
+    wb.NMTFree(memAlloc2);
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.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
+    wb.NMTFree(memAlloc1);
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+  }
+}
--- a/test/runtime/NMT/PrintNMTStatistics.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/runtime/NMT/PrintNMTStatistics.java	Mon Apr 15 08:51:19 2013 +0200
@@ -27,7 +27,9 @@
  * @bug 8005936
  * @summary Make sure PrintNMTStatistics works on normal JVM exit
  * @library /testlibrary /testlibrary/whitebox
- * @run compile PrintNMTStatistics.java
+ * @build PrintNMTStatistics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main PrintNMTStatistics
  */
 
 import com.oracle.java.testlibrary.*;
@@ -52,13 +54,15 @@
 
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
         "-XX:+UnlockDiagnosticVMOptions",
+        "-Xbootclasspath/a:.",
+        "-XX:+WhiteBoxAPI",
         "-XX:NativeMemoryTracking=summary",
-        "+XX:+PrintNMTStatistics",
+        "-XX:+PrintNMTStatistics",
         "PrintNMTStatistics",
         "test");
 
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Java Heap  (reserved=");
+    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/ThreadedMallocTestType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ThreadedMallocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class ThreadedMallocTestType {
+  public static long memAlloc1;
+  public static long memAlloc2;
+  public static long memAlloc3;
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    Thread allocThread = new Thread() {
+      public void run() {
+        // Alloc memory using the WB api
+        memAlloc1 = wb.NMTMalloc(128 * 1024);
+        memAlloc2 = wb.NMTMalloc(256 * 1024);
+        memAlloc3 = wb.NMTMalloc(512 * 1024);
+      }
+    };
+
+    allocThread.start();
+    allocThread.join();
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.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=896KB, committed=896KB)");
+
+    Thread freeThread = new Thread() {
+      public void run() {
+        // Free the memory allocated by NMTMalloc
+        wb.NMTFree(memAlloc1);
+        wb.NMTFree(memAlloc2);
+        wb.NMTFree(memAlloc3);
+      }
+    };
+
+    freeThread.start();
+    freeThread.join();
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.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/ThreadedVirtualAllocTestType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ThreadedVirtualAllocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class ThreadedVirtualAllocTestType {
+  public static long addr;
+  public static final WhiteBox wb = WhiteBox.getWhiteBox();
+  public static final long commitSize = 128 * 1024;
+  public static final long reserveSize = 512 * 1024;
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    Thread reserveThread = new Thread() {
+      public void run() {
+        addr = wb.NMTReserveMemory(reserveSize);
+      }
+    };
+    reserveThread.start();
+    reserveThread.join();
+
+    mergeData();
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=0KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test");
+
+    Thread commitThread = new Thread() {
+      public void run() {
+        wb.NMTCommitMemory(addr, commitSize);
+      }
+    };
+    commitThread.start();
+    commitThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=128KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
+
+    Thread uncommitThread = new Thread() {
+      public void run() {
+        wb.NMTUncommitMemory(addr, commitSize);
+      }
+    };
+    uncommitThread.start();
+    uncommitThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=0KB)");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
+
+    Thread releaseThread = new Thread() {
+      public void run() {
+        wb.NMTReleaseMemory(addr, reserveSize);
+      }
+    };
+    releaseThread.start();
+    releaseThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+    output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
+  }
+
+  public static void mergeData() throws Exception {
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/VirtualAllocTestType.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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 Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build VirtualAllocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class VirtualAllocTestType {
+
+  public static WhiteBox wb = WhiteBox.getWhiteBox();
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    long commitSize = 128 * 1024;
+    long reserveSize = 256 * 1024;
+    long addr;
+
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    addr = wb.NMTReserveMemory(reserveSize);
+    mergeData();
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=0KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test");
+
+    wb.NMTCommitMemory(addr, commitSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=128KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
+
+    wb.NMTUncommitMemory(addr, commitSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=0KB)");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
+
+    wb.NMTReleaseMemory(addr, reserveSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
+  }
+
+  public static void mergeData() throws Exception {
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/interned/SanityTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -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.
+ */
+
+/*
+ * @test SanityTest
+ * @summary Sanity check of String.intern() & GC
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SanityTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SanityTest
+ */
+
+import java.util.*;
+import sun.hotspot.WhiteBox;
+
+
+public class SanityTest {
+    public static Object tmp;
+    public static void main(String... args) {
+
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        StringBuilder sb = new StringBuilder();
+        sb.append("1234x"); sb.append("x56789");
+        String str = sb.toString();
+
+        if (wb.isInStringTable(str)) {
+            throw new RuntimeException("String " + str + " is already interned");
+        }
+        str.intern();
+        if (!wb.isInStringTable(str)) {
+            throw new RuntimeException("String " + str + " is not interned");
+        }
+        str = sb.toString();
+        wb.fullGC();
+        if (wb.isInStringTable(str)) {
+            throw new RuntimeException("String " + str + " is in StringTable even after GC");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_env.sh	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,193 @@
+#!/bin/sh
+#
+#  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.
+# 
+
+#
+# This Environment script was written to capture typically used environment
+# setup for a given shell test. 
+#
+
+# TESTJAVA can be a JDK or JRE. If JRE you need to set COMPILEJAVA
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+
+# COMPILEJAVA requires a JDK, some shell test use javac,jar,etc 
+if [ "${COMPILEJAVA}" = "" ]
+then
+ echo "COMPILEJAVA not set.  Using TESTJAVA as default"
+ COMPILEJAVA=${TESTJAVA}
+fi
+echo "COMPILEJAVA=${COMPILEJAVA}"
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASES not set.  Using "." as default"
+  TESTCLASSES=.
+fi
+echo "TESTCLASSES=${TESTCLASSES}"
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  SunOS | Linux | Darwin )
+    NULL=/dev/null
+    PS=":"
+    FS="/"
+    RM=/bin/rm
+    CP=/bin/cp
+    MV=/bin/mv
+    ;;
+  Windows_* )
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    RM=rm
+    CP=cp
+    MV=mv
+    ;;
+  CYGWIN_* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    RM=rm
+    CP=cp
+    MV=mv
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
+export NULL PS FS RM CP MV
+echo "NULL =${NULL}"
+echo "PS =${PS}"
+echo "FS =${FS}"
+echo "RM =${RM}"
+echo "CP =${CP}"
+echo "MV =${MV}"
+
+# jtreg -classpathappend:<path>
+JEMMYPATH=${CPAPPEND}
+CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
+echo "CLASSPATH =${CLASSPATH}"
+
+# Current directory is scratch directory 
+THIS_DIR=.
+echo "THIS_DIR=${THIS_DIR}"
+
+# Check to ensure the java defined actually works
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
+if [ $? != 0 ]; then
+  echo "Wrong TESTJAVA or TESTVMOPTS:"
+  echo $TESTJAVA TESTVMOPTS
+  exit 1
+fi
+
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion > vm_version.out 2>&1
+
+VM_TYPE="unknown"
+grep "Server" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_TYPE="server"
+fi
+grep "Client" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_TYPE="client"
+fi
+
+VM_BITS="32"
+grep "64-Bit" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_BITS="64"
+fi
+
+VM_OS="unknown"
+grep "solaris" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="solaris"
+fi
+grep "linux" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="linux"
+fi
+grep "windows" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="windows"
+fi
+grep "bsd" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="bsd"
+fi
+
+VM_CPU="unknown"
+grep "sparc" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="sparc"
+  if [ $VM_BITS = "64" ]
+  then
+    VM_CPU="sparcv9"
+  fi
+fi
+grep "x86" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="i386"
+fi
+grep "amd64" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="amd64"
+fi
+grep "arm" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="arm"
+fi
+grep "ppc" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="ppc"
+fi
+grep "ia64" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_CPU="ia64"
+fi
+export VM_TYPE VM_BITS VM_OS VM_CPU
+echo "VM_TYPE=${VM_TYPE}"
+echo "VM_BITS=${VM_BITS}"
+echo "VM_OS=${VM_OS}"
+echo "VM_CPU=${VM_CPU}"
--- a/test/testlibrary/OutputAnalyzerTest.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/testlibrary/OutputAnalyzerTest.java	Mon Apr 15 08:51:19 2013 +0200
@@ -36,6 +36,11 @@
     String stdout = "aaaaaa";
     String stderr = "bbbbbb";
 
+    // Regexps used for testing pattern matching of the test input
+    String stdoutPattern = "[a]";
+    String stderrPattern = "[b]";
+    String nonExistingPattern = "[c]";
+
     OutputAnalyzer output = new OutputAnalyzer(stdout, stderr);
 
     if (!stdout.equals(output.getStdout())) {
@@ -99,10 +104,73 @@
     }
 
     try {
-      output.stderrShouldNotContain(stderr);
-      throw new Exception("shouldContain() failed to throw exception");
+        output.stderrShouldNotContain(stderr);
+        throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    // Should match
+    try {
+        output.shouldMatch(stdoutPattern);
+        output.stdoutShouldMatch(stdoutPattern);
+        output.shouldMatch(stderrPattern);
+        output.stderrShouldMatch(stderrPattern);
+    } catch (RuntimeException e) {
+        throw new Exception("shouldMatch() failed", e);
+    }
+
+    try {
+        output.shouldMatch(nonExistingPattern);
+        throw new Exception("shouldMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stdoutShouldMatch(stderrPattern);
+        throw new Exception(
+                "stdoutShouldMatch() failed to throw exception");
     } catch (RuntimeException e) {
-      // expected
+        // expected
+    }
+
+    try {
+        output.stderrShouldMatch(stdoutPattern);
+        throw new Exception(
+                "stderrShouldMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    // Should not match
+    try {
+        output.shouldNotMatch(nonExistingPattern);
+        output.stdoutShouldNotMatch(nonExistingPattern);
+        output.stderrShouldNotMatch(nonExistingPattern);
+    } catch (RuntimeException e) {
+        throw new Exception("shouldNotMatch() failed", e);
+    }
+
+    try {
+        output.shouldNotMatch(stdoutPattern);
+        throw new Exception("shouldNotMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stdoutShouldNotMatch(stdoutPattern);
+        throw new Exception("shouldNotMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stderrShouldNotMatch(stderrPattern);
+        throw new Exception("shouldNotMatch() 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/JDKToolLauncher.java	Mon Apr 15 08:51:19 2013 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.JDKToolFinder;
+import com.oracle.java.testlibrary.ProcessTools;
+
+/**
+ * A utility for constructing command lines for starting JDK tool processes.
+ *
+ * The JDKToolLauncher can in particular be combined with a
+ * java.lang.ProcessBuilder to easily run a JDK tool. For example, the
+ * following code run {@code jmap -heap} against a process with GC logging
+ * turned on for the {@code jmap} process:
+ *
+ * <pre>
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ *                                       .addVMArg("-XX:+PrintGC");
+ *                                       .addVMArg("-XX:+PrintGCDetails")
+ *                                       .addToolArg("-heap")
+ *                                       .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * </pre>
+ */
+public class JDKToolLauncher {
+    private final String executable;
+    private final List<String> vmArgs = new ArrayList<String>();
+    private final List<String> toolArgs = new ArrayList<String>();
+
+    private JDKToolLauncher(String tool) {
+        executable = JDKToolFinder.getJDKTool(tool);
+        vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
+    }
+
+    /**
+     * Creates a new JDKToolLauncher for the specified tool.
+     *
+     * @param tool The name of the tool
+     * @return A new JDKToolLauncher
+     */
+    public static JDKToolLauncher create(String tool) {
+        return new JDKToolLauncher(tool);
+    }
+
+    /**
+     * Adds an argument to the JVM running the tool.
+     *
+     * The JVM arguments are passed to the underlying JVM running the tool.
+     * Arguments will automatically be prepended with "-J".
+     *
+     * Any platform specific arguments required for running the tool are
+     * automatically added.
+     *
+     *
+     * @param arg The argument to VM running the tool
+     * @return The JDKToolLauncher instance
+     */
+    public JDKToolLauncher addVMArg(String arg) {
+        vmArgs.add("-J" + arg);
+        return this;
+    }
+
+    /**
+     * Adds an argument to the tool.
+     *
+     * @param arg The argument to the tool
+     * @return The JDKToolLauncher instance
+     */
+    public JDKToolLauncher addToolArg(String arg) {
+        toolArgs.add(arg);
+        return this;
+    }
+
+    /**
+     * Returns the command that can be used for running the tool.
+     *
+     * @return An array whose elements are the arguments of the command.
+     */
+    public String[] getCommand() {
+        List<String> command = new ArrayList<String>();
+        command.add(executable);
+        command.addAll(vmArgs);
+        command.addAll(toolArgs);
+        return command.toArray(new String[command.size()]);
+    }
+}
--- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Mon Apr 15 08:51:19 2013 +0200
@@ -24,6 +24,8 @@
 package com.oracle.java.testlibrary;
 
 import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public final class OutputAnalyzer {
 
@@ -142,15 +144,112 @@
   }
 
   /**
+   * Verify that the stdout and stderr contents of output buffer matches
+   * the pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void shouldMatch(String pattern) {
+      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stdout/stderr: [" + stdout + stderr
+                  + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer matches the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void stdoutShouldMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (!matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stdout: [" + stdout + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer matches the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void stderrShouldMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (!matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stderr: [" + stderr + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer does not
+   * match the pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void shouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stdout: [" + stdout + "]\n");
+      }
+      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stderr: [" + stderr + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer does not match the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void stdoutShouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stdout: [" + stdout + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer does not match the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void stderrShouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' 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);
-    }
+      if (getExitValue() != expectedExitValue) {
+          throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue);
+      }
   }
 
   /**
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu Apr 04 11:57:04 2013 +0200
+++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Mon Apr 15 08:51:19 2013 +0200
@@ -80,18 +80,34 @@
   public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
 
   // NMT
-  public native boolean NMTAllocTest();
-  public native boolean NMTFreeTestMemory();
+  public native long NMTMalloc(long size);
+  public native void NMTFree(long mem);
+  public native long NMTReserveMemory(long size);
+  public native void NMTCommitMemory(long addr, long size);
+  public native void NMTUncommitMemory(long addr, long size);
+  public native void NMTReleaseMemory(long addr, long size);
   public native boolean NMTWaitForDataMerge();
 
   // Compiler
   public native void    deoptimizeAll();
   public native boolean isMethodCompiled(Method method);
-  public native boolean isMethodCompilable(Method method);
+  public boolean isMethodCompilable(Method method) {
+      return isMethodCompilable(method, -1 /*any*/);
+  }
+  public native boolean isMethodCompilable(Method method, int compLevel);
   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 boolean testSetDontInlineMethod(Method method, boolean value);
   public native int     getCompileQueuesSize();
+  public native boolean testSetForceInlineMethod(Method method, boolean value);
+  public native boolean enqueueMethodForCompilation(Method method, int compLevel);
+  public native void    clearMethodState(Method method);
+
+  //Intered strings
+  public native boolean isInStringTable(String str);
+
+  // force Full GC
+  public native void fullGC();
 }