changeset 7349:a6df8a2a8eb0 default tip

Merge hs25.60-b12
author andrew
date Wed, 22 Apr 2015 06:24:15 +0100
parents 6d54b1140edf (current diff) ccca7162738e (diff)
children
files agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java make/linux/makefiles/arm.make make/linux/makefiles/build_vm_def.sh make/linux/makefiles/gcc.make make/linux/makefiles/ppc.make make/linux/makefiles/vm.make make/linux/platform_arm make/linux/platform_ppc src/cpu/zero/vm/cppInterpreter_zero.cpp src/os/linux/vm/os_linux.cpp src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp src/share/vm/interpreter/bytecodeInterpreter.cpp src/share/vm/utilities/vmError.cpp
diffstat 286 files changed, 8992 insertions(+), 3905 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Feb 27 09:59:29 2015 +0000
+++ b/.hgtags	Wed Apr 22 06:24:15 2015 +0100
@@ -501,6 +501,8 @@
 00cf2b6f51b9560b01030e8f4c28c466f0b21fe3 hs25.20-b23
 19408d5fd31c25ce60c43dd33e92b96e8df4a4ea jdk8u20-b25
 eaa4074a7e3975cd33ec55e6b584586e2ac681bd jdk8u20-b26
+7c9925f21c2529a88eb64b8039cc080f60b85e01 jdk8u20-b31
+7edb04063a423e278fe34a0006d25fee198f495e jdk8u20-b32
 4828415ebbf11e205dcc08e97ad5ae7dd03522f9 jdk8u40-b00
 d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e hs25.40-b01
 f0afba33c928ddaa2d5f003b90d683c143f78ea3 hs25.40-b02
@@ -544,6 +546,25 @@
 6467bdd4d22d8b140844dc847c43b9ba7cb0bbd1 jdk8u25-b16
 28b50d07f6f8c5a567b6a25e95a423948114a004 jdk8u25-b17
 639abc668bfe995dba811dd35411b9ea8a9041cd jdk8u25-b18
+c3528699fb33fe3eb1d117504184ae7ab2507aa1 jdk8u25-b31
+631f0c7b49c091c6865d79d248d6551a270ac22f jdk8u25-b32
+4e1f52384f9ffa803838acad545cd63de48a7b35 jdk8u25-b33
+5bb683bbe2c74876d585b5c3232fc3aab7b23e97 jdk8u31-b00
+5bb686ae3b89f8aa1c74331b2d24e2a5ebd43448 jdk8u31-b01
+087678da96603c9705b38b6cc4a6569ac7b4420a jdk8u31-b02
+401cbaa475b4efe53153119ab87a82b217980a7f jdk8u31-b03
+060cdf93040c1bfa5fdf580da5e9999042632cc8 jdk8u31-b04
+6e56d7f1634f6c4cd4196e699c06e6ca2e6d6efb jdk8u31-b05
+271a32147391d08b0f338d9353330e2b5584d580 jdk8u31-b06
+e9f815c3f21cf2febd8e3c185917c1519aa52d9a jdk8u31-b07
+cc74ca22516644867be3b8db6c1f8d05ab4f6c27 jdk8u31-b08
+245d29ed5db5ad6914eb0c9fe78b9ba26122c478 jdk8u31-b09
+d7b6bdd51abe68b16411d5b292fb830a43c5bc09 jdk8u31-b10
+9906d432d6dbd2cda242e3f3cfde7cf6c90245bf jdk8u31-b11
+e13839545238d1ecf17f0489bb6fb765de46719a jdk8u31-b12
+4206e725d584be942c25ff46ff23d8e299ca4a4c jdk8u31-b13
+b517d3a9aebf0fee64808f9a7c0ef8e0b82d5ed3 jdk8u31-b31
+15d8108258cb60a58bdd03b9ff8e77dd6727a804 jdk8u31-b32
 1b3abbeee961dee49780c0e4af5337feb918c555 jdk8u40-b10
 f10fe402dfb1543723b4b117a7cba3ea3d4159f1 hs25.40-b15
 99372b2fee0eb8b3452f47230e84aa6e97003184 jdk8u40-b11
@@ -563,3 +584,53 @@
 31d3306aad29e39929418ed43f28212a5f5306a3 jdk8u40-b18
 f8fc5cbe082ce0fb0c6c1dcd39493a16ed916353 hs25.40-b23
 d9349fa8822336e0244da0a8448f3e6b2d62741d jdk8u40-b19
+c3933f52eeb33f70ee562464edddfe9f01d944fd jdk8u40-b20
+d2e9a6bec4f2eec8506eed16f7324992a85d8480 hs25.40-b24
+25ec4a67433744bbe3406e5069e7fd1876ebbf2f jdk8u40-b21
+0f0cb4eeab2d871274f4ffdcd6017d2fdfa89238 hs25.40-b25
+0ee548a1cda08c884eccd563e2d5fdb6ee769b5a jdk8u40-b22
+0e67683b700174eab71ea205d1cfa4f1cf4523ba jdk8u40-b23
+fa4e797f61e6dda1a60e06944018213bff2a1b76 jdk8u40-b24
+698dd28ecc785ffc43e3f12266b13e85382c26a8 jdk8u40-b25
+f39b6944ad447269b81e06ca5da9edff9e9e67c8 jdk8u40-b26
+6824e2475e0432e27f9cc51838bc34ea5fbf5113 jdk8u40-b27
+b95f13f05f553309cd74d6ccf8fcedb259c6716c jdk8u45-b00
+41c3c456e326185053f0654be838f4b0bfb38078 jdk8u45-b01
+626fd8c2eec63e2a2dff3839bfe12c0431bf00a4 jdk8u45-b02
+f41aa01b0a043611ee0abcb81a40f7d80085ec27 jdk8u45-b03
+2f586e3c4b6db807ac6036b485b2890ff82f7bfd jdk8u45-b04
+344ff6e45a1e2960ac4a583f63ebfb54cd52e6b4 jdk8u45-b05
+3afa9cc6e8d537ee456b8e12d1abb1da520b5ddc jdk8u45-b06
+5871f3dd9b4a2c4b44e7da2184f4430323e0c04b jdk8u45-b07
+35c7330b68e21d0dfaaedaaf74b794fd10606e9c jdk8u45-b08
+35d8318de0b6d4e68e2e0a04f6e20cafd113ca54 jdk8u45-b09
+a9f5786079202b74b3651e1097c0b2341b2178b9 jdk8u45-b10
+f4822d12204179e6a3e7aaf98991b6171670cbf2 jdk8u45-b11
+dc29108bcbcbfcd49eaa9135368306dc85db73a6 jdk8u45-b12
+efbf340fc7f56e49735111c23cef030413146409 jdk8u45-b13
+5321d26956b283b7cb73b04b91db41c7c9fe9158 jdk8u45-b14
+d9349fa8822336e0244da0a8448f3e6b2d62741d jdk8u60-b00
+d9349fa8822336e0244da0a8448f3e6b2d62741d hs25.60-b00
+ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01
+5fa73007ceb92a13742fc4a24ec935a6494f8045 hs25.60-b02
+702cc6067686acaa45f7b455b7490edc056c2ae0 jdk8u60-b01
+1f6ba0d2923dadba87aac4ed779dd1ed0161ec2b hs25.60-b03
+38f6080523831ae9a6907c780f2042b82f3213ca jdk8u60-b02
+9d6eb2757167744a17ea71f8b860430d70941eda jdk8u60-b03
+0fb1ac49ae7764c5d7c6dfb9fe046d0e1a4eb5aa hs25.60-b04
+586a449cd30332dd53c0f74bf2ead6f3d4724bfc jdk8u60-b04
+74931e85352be8556eaa511ca0dd7c38fe272ec3 hs25.60-b05
+b13f1890afb8abc31ecb9c21fd2ba95aba3e33f8 jdk8u60-b05
+b17a8a22a0344e3c93e2e4677de20d35f99cf4f5 hs25.60-b06
+7b70923c8e04920b60278f90ad23a63c773cee7b jdk8u60-b06
+d51ef6da82b486e7b2b3c08eef9ca0a186935ded hs25.60-b07
+353e580ce6878d80c7b7cd27f8ad24609b12c58b jdk8u60-b07
+a72a4192a36d6d84766d6135fe6515346c742007 hs25.60-b08
+bf68e15dc8fe73eeb1eb3c656df51fdb1f707a97 jdk8u60-b08
+d937e6a0674841d670232ecf1611f52e1ae998e7 hs25.60-b09
+f1058b5c6294235d8ad032dcc72c8f8bc202cb5a jdk8u60-b09
+57a14c3927eba6372d909ae164fa90bb9b6a6ce4 hs25.60-b10
+8e4518dc2b38957072704ffe4cbf29f046dc9325 jdk8u60-b10
+64a32bc18e88eed6131ed036dc3e10e566ef339b hs25.60-b11
+d8f133adf05d310bd7e1d9adf32cbeb71ff33c37 jdk8u60-b11
+4390345de45c7768c04bfafabf006a401824c5b5 hs25.60-b12
--- a/THIRD_PARTY_README	Fri Feb 27 09:59:29 2015 +0000
+++ b/THIRD_PARTY_README	Wed Apr 22 06:24:15 2015 +0100
@@ -1250,7 +1250,7 @@
 
 -------------------------------------------------------------------------------
 
-%% This notice is provided with respect to libpng 1.5.4, which may be 
+%% This notice is provided with respect to libpng 1.6.16, which may be
 included with JRE 8, JDK 8, and OpenJDK 8.
 
 --- begin of LICENSE ---
@@ -1266,8 +1266,8 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are
-Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
+libpng versions 1.2.6, August 15, 2004, through 1.6.16, December 22, 2014, are
+Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
 
@@ -1364,7 +1364,7 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-July 7, 2011
+December 22, 2014
 
 --- end of LICENSE ---
 
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/os/bsd/MacosxDebuggerLocal.m	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
 #import <Foundation/Foundation.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
-#include <JavaVM/jni.h>
+#include <jni.h>
 
 #import <mach/mach.h>
 #import <mach/mach_types.h>
--- a/agent/src/os/bsd/Makefile	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/os/bsd/Makefile	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -50,9 +50,9 @@
 	ps_core.c
 OBJS    = $(SOURCES:.c=.o)
 OBJSPLUS = MacosxDebuggerLocal.o sadis.o $(OBJS)
-EXTINCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers -I.
+EXTINCLUDE = -I.
 EXTCFLAGS = -m64 -D__APPLE__ -framework JavaNativeFoundation
-FOUNDATIONFLAGS = -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
+FOUNDATIONFLAGS = -framework Foundation -framework JavaNativeFoundation -framework Security -framework CoreFoundation
 LIBSA = $(ARCH)/libsaproc.dylib
 endif   # Darwin
 
--- a/agent/src/os/linux/libproc.h	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/os/linux/libproc.h	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 #include <stdint.h>
 #include "proc_service.h"
 
-#if defined(arm) || defined(ppc)
+#ifdef ALT_SASRCDIR
 #include "libproc_md.h"
 #endif
 
--- a/agent/src/os/linux/ps_proc.c	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/os/linux/ps_proc.c	Wed Apr 22 06:24:15 2015 +0100
@@ -27,9 +27,11 @@
 #include <string.h>
 #include <signal.h>
 #include <errno.h>
+#include <elf.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/ptrace.h>
+#include <sys/uio.h>
 #include "libproc_impl.h"
 
 #if defined(x86_64) && !defined(amd64)
@@ -138,6 +140,15 @@
    return false;
  }
  return true;
+#elif defined(PTRACE_GETREGSET)
+ struct iovec iov;
+ iov.iov_base = user;
+ iov.iov_len = sizeof(*user);
+ if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void*) &iov) < 0) {
+   print_debug("ptrace(PTRACE_GETREGSET, ...) failed for lwp %d\n", pid);
+   return false;
+ }
+ return true;
 #else
  print_debug("ptrace(PTRACE_GETREGS, ...) not supported\n");
  return false;
--- a/agent/src/os/solaris/proc/saproc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/os/solaris/proc/saproc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -314,7 +314,7 @@
     handle = dlopen(name, mode);
   }
   if (_libsaproc_debug) {
-    printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%x\n", name, handle);
+    printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle);
   }
   return handle;
 }
@@ -661,30 +661,30 @@
   // read FileMapHeader
   size_t n = read(fd, pheader, sizeof(struct FileMapHeader));
   if (n != sizeof(struct FileMapHeader)) {
-    free(pheader);
-    close(fd);
     char errMsg[ERR_MSG_SIZE];
     sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa);
+    close(fd);
+    free(pheader);
     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
   }
 
   // check file magic
   if (pheader->_magic != 0xf00baba2) {
-    free(pheader);
-    close(fd);
     char errMsg[ERR_MSG_SIZE];
     sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2",
                    classes_jsa, pheader->_magic);
+    close(fd);
+    free(pheader);
     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
   }
 
   // check version
   if (pheader->_version != CURRENT_ARCHIVE_VERSION) {
-    free(pheader);
-    close(fd);
     char errMsg[ERR_MSG_SIZE];
     sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d",
                    classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION);
+    close(fd);
+    free(pheader);
     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
   }
 
--- a/agent/src/share/classes/com/sun/java/swing/action/ActionManager.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/com/sun/java/swing/action/ActionManager.java	Wed Apr 22 06:24:15 2015 +0100
@@ -46,6 +46,11 @@
         return manager;
     }
 
+    protected static void setInstance(ActionManager m)
+    {
+        manager = m;
+    }
+
     protected abstract void addActions();
 
     protected void addAction(String cmdname, Action action)
@@ -90,6 +95,6 @@
 
     private HashMap actions;
     private static ActionUtilities utilities = new ActionUtilities();
-    protected static ActionManager manager;
+    private static ActionManager manager;
 
 }
--- a/agent/src/share/classes/com/sun/java/swing/ui/CommonToolBar.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/com/sun/java/swing/ui/CommonToolBar.java	Wed Apr 22 06:24:15 2015 +0100
@@ -46,7 +46,7 @@
     {
         this.manager = manager;
         statusBar = status;
-        buttonSize = new Dimension(CommonUI.buttconPrefSize);
+        buttonSize = new Dimension(CommonUI.getButtconPrefSize());
         buttonInsets = new Insets(0, 0, 0, 0);
         addComponents();
     }
--- a/agent/src/share/classes/com/sun/java/swing/ui/CommonUI.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/com/sun/java/swing/ui/CommonUI.java	Wed Apr 22 06:24:15 2015 +0100
@@ -373,20 +373,25 @@
         comp.setCursor(Cursor.getPredefinedCursor(0));
     }
 
-    public static final int BUTTON_WIDTH = 100;
-    public static final int BUTTON_HEIGHT = 26;
-    public static final int BUTTCON_WIDTH = 28;
-    public static final int BUTTCON_HEIGHT = 28;
-    public static final int SM_BUTTON_WIDTH = 72;
-    public static final int SM_BUTTON_HEIGHT = 26;
-    public static final int LABEL_WIDTH = 100;
-    public static final int LABEL_HEIGHT = 20;
-    public static final int TEXT_WIDTH = 150;
-    public static final int TEXT_HEIGHT = 20;
-    public static Dimension buttonPrefSize = new Dimension(100, 26);
-    public static Dimension buttconPrefSize = new Dimension(28, 28);
-    public static Dimension smbuttonPrefSize = new Dimension(72, 26);
-    public static Dimension labelPrefSize = new Dimension(100, 20);
-    public static Dimension textPrefSize = new Dimension(150, 20);
+    public static Dimension getButtconPrefSize()
+    {
+        return buttconPrefSize;
+    }
+
+    private static final int BUTTON_WIDTH = 100;
+    private static final int BUTTON_HEIGHT = 26;
+    private static final int BUTTCON_WIDTH = 28;
+    private static final int BUTTCON_HEIGHT = 28;
+    private static final int SM_BUTTON_WIDTH = 72;
+    private static final int SM_BUTTON_HEIGHT = 26;
+    private static final int LABEL_WIDTH = 100;
+    private static final int LABEL_HEIGHT = 20;
+    private static final int TEXT_WIDTH = 150;
+    private static final int TEXT_HEIGHT = 20;
+    private static final Dimension buttonPrefSize = new Dimension(100, 26);
+    private static final Dimension buttconPrefSize = new Dimension(28, 28);
+    private static final Dimension smbuttonPrefSize = new Dimension(72, 26);
+    private static final Dimension labelPrefSize = new Dimension(100, 20);
+    private static final Dimension textPrefSize = new Dimension(150, 20);
 
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java	Wed Apr 22 06:24:15 2015 +0100
@@ -51,6 +51,9 @@
   private static final int C_INT32_SIZE = 4;
   private static final int C_INT64_SIZE = 8;
   private static int pointerSize = UNINITIALIZED_SIZE;
+  // Counter to ensure read loops terminate:
+  private static final int MAX_DUPLICATE_DEFINITIONS = 100;
+  private int duplicateDefCount = 0;
 
   private static final boolean DEBUG;
   static {
@@ -166,6 +169,10 @@
     typeEntrySizeOffset           = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
     typeEntryArrayStride          = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
 
+    if (typeEntryArrayStride == 0L) {
+      throw new RuntimeException("zero stride: cannot read types.");
+    }
+
     // Start iterating down it until we find an entry with no name
     Address typeNameAddr = null;
     do {
@@ -192,7 +199,11 @@
       }
 
       entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
-    } while (typeNameAddr != null);
+    } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
+
+    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
+      throw new RuntimeException("too many duplicate definitions");
+    }
   }
 
   private void initializePrimitiveTypes() {
@@ -395,6 +406,10 @@
     structEntryAddressOffset      = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
     structEntryArrayStride        = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");
 
+    if (structEntryArrayStride == 0L) {
+      throw new RuntimeException("zero stride: cannot read types.");
+    }
+
     // Fetch the address of the VMStructEntry*
     Address entryAddr = lookupInProcess("gHotSpotVMStructs");
     // Dereference this once to get the pointer to the first VMStructEntry
@@ -472,6 +487,11 @@
     intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
     intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");
 
+    if (intConstantEntryArrayStride == 0L) {
+      throw new RuntimeException("zero stride: cannot read types.");
+    }
+
+
     // Fetch the address of the VMIntConstantEntry*
     Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
     // Dereference this once to get the pointer to the first VMIntConstantEntry
@@ -501,12 +521,17 @@
           } else {
             System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
                                "had its value declared as " + value + " twice. Continuing.");
+            duplicateDefCount++;
           }
         }
       }
 
       entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
-    } while (nameAddr != null);
+    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
+
+    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
+      throw new RuntimeException("too many duplicate definitions");
+    }
   }
 
   private void readVMLongConstants() {
@@ -519,6 +544,10 @@
     longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
     longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");
 
+    if (longConstantEntryArrayStride == 0L) {
+      throw new RuntimeException("zero stride: cannot read types.");
+    }
+
     // Fetch the address of the VMLongConstantEntry*
     Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
     // Dereference this once to get the pointer to the first VMLongConstantEntry
@@ -548,12 +577,17 @@
           } else {
             System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
                                "had its value declared as " + value + " twice. Continuing.");
+            duplicateDefCount++;
           }
         }
       }
 
       entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
-    } while (nameAddr != null);
+    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
+
+    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
+      throw new RuntimeException("too many duplicate definitions.");
+    }
   }
 
   private BasicType lookupOrFail(String typeName) {
@@ -740,9 +774,10 @@
             }
 
             if (!typeNameIsPointerType(typeName)) {
-            System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
-                               "had its size declared as " + size + " twice. Continuing.");
-        }
+                System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
+                                   "had its size declared as " + size + " twice. Continuing.");
+                duplicateDefCount++;
+            }
         }
 
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/G1YCType.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc_interface;
+
+//These definitions should be kept in sync with the definitions in the HotSpot
+//code.
+
+public enum G1YCType {
+  Normal ("Normal"),
+  InitialMark ("Initial Mark"),
+  DuringMark ("During Mark"),
+  Mixed ("Mixed"),
+  G1YCTypeEndSentinel ("Unknown");
+
+  private final String value;
+
+  G1YCType(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/GCCause.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc_interface;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum GCCause {
+  _java_lang_system_gc ("System.gc()"),
+  _full_gc_alot ("FullGCAlot"),
+  _scavenge_alot ("ScavengeAlot"),
+  _allocation_profiler ("Allocation Profiler"),
+  _jvmti_force_gc ("JvmtiEnv ForceGarbageCollection"),
+  _gc_locker ("GCLocker Initiated GC"),
+  _heap_inspection ("Heap Inspection Initiated GC"),
+  _heap_dump ("Heap Dump Initiated GC"),
+
+  _no_gc ("No GC"),
+  _no_cause_specified ("Unknown GCCause"),
+  _allocation_failure ("Allocation Failure"),
+
+  _tenured_generation_full ("Tenured Generation Full"),
+  _metadata_GC_threshold ("Metadata GC Threshold"),
+
+  _cms_generation_full ("CMS Generation Full"),
+  _cms_initial_mark ("CMS Initial Mark"),
+  _cms_final_remark ("CMS Final Remark"),
+  _cms_concurrent_mark ("CMS Concurrent Mark"),
+
+  _old_generation_expanded_on_last_scavenge ("Old Generation Expanded On Last Scavenge"),
+  _old_generation_too_full_to_scavenge ("Old Generation Too Full To Scavenge"),
+  _adaptive_size_policy ("Ergonomics"),
+
+  _g1_inc_collection_pause ("G1 Evacuation Pause"),
+  _g1_humongous_allocation ("G1 Humongous Allocation"),
+
+  _last_ditch_collection ("Last ditch collection"),
+  _last_gc_cause ("ILLEGAL VALUE - last gc cause - ILLEGAL VALUE");
+
+  private final String value;
+
+  GCCause(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/GCName.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc_interface;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum GCName {
+  ParallelOld ("ParallelOld"),
+  SerialOld ("SerialOld"),
+  PSMarkSweep ("PSMarkSweep"),
+  ParallelScavenge ("ParallelScavenge"),
+  DefNew ("DefNew"),
+  ParNew ("ParNew"),
+  G1New ("G1New"),
+  ConcurrentMarkSweep ("ConcurrentMarkSweep"),
+  G1Old ("G1Old"),
+  GCNameEndSentinel ("GCNameEndSentinel");
+
+  private final String value;
+
+  GCName(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/GCWhen.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc_interface;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum GCWhen {
+  BeforeGC ("Before GC"),
+  AfterGC ("After GC"),
+  GCWhenEndSentinel ("GCWhenEndSentinel");
+
+  private final String value;
+
+  GCWhen(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/ReferenceType.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc_interface;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum ReferenceType {
+  REF_NONE ("None reference"),       // Regular class
+  REF_OTHER ("Other reference"),     // Subclass of java/lang/ref/Reference, but not subclass of one of the classes below
+  REF_SOFT ("Soft reference"),       // Subclass of java/lang/ref/SoftReference
+  REF_WEAK ("Weak reference"),       // Subclass of java/lang/ref/WeakReference
+  REF_FINAL ("Final reference"),     // Subclass of java/lang/ref/FinalReference
+  REF_PHANTOM ("Phantom reference"); // Subclass of java/lang/ref/PhantomReference
+
+  private final String value;
+
+  ReferenceType(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/AdaptiveFreeList.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,77 @@
+/*
+ * @(#)AdaptiveFreeList.java
+ *
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.types.CIntegerField;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
+
+public class AdaptiveFreeList extends VMObject {
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+      public void update(Observable o, Object data) {
+        initialize(VM.getVM().getTypeDataBase());
+      }
+    });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) {
+    Type type = db.lookupType("AdaptiveFreeList<FreeChunk>");
+    sizeField = type.getCIntegerField("_size");
+    countField = type.getCIntegerField("_count");
+    headerSize = type.getSize();
+  }
+
+  // Fields
+  private static CIntegerField sizeField;
+  private static CIntegerField countField;
+  private static long          headerSize;
+
+  //Constructor
+  public AdaptiveFreeList(Address address) {
+    super(address);
+  }
+
+  // Accessors
+  public long size() {
+    return sizeField.getValue(addr);
+  }
+
+  public long count() {
+    return  countField.getValue(addr);
+  }
+
+  public static long sizeOf() {
+    return headerSize;
+  }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +24,29 @@
 
 package sun.jvm.hotspot.memory;
 
-import java.io.*;
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.utilities.*;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.debugger.Debugger;
+import sun.jvm.hotspot.oops.ObjectHeap;
+import sun.jvm.hotspot.oops.Oop;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.AddressField;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
+import sun.jvm.hotspot.utilities.Assert;
 
 public class CompactibleFreeListSpace extends CompactibleSpace {
    private static AddressField collectorField;
-
-   // for free size, three fields
-   //       FreeBlockDictionary* _dictionary;        // ptr to dictionary for large size blocks
-   //       FreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks
-   //       LinearAllocBlock _smallLinearAllocBlock; // small linear alloc in TLAB
    private static AddressField indexedFreeListField;
    private static AddressField dictionaryField;
    private static long         smallLinearAllocBlockFieldOffset;
-   private static long indexedFreeListSizeOf;
 
    private int    heapWordSize;     // 4 for 32bit, 8 for 64 bits
    private int    IndexSetStart;    // for small indexed list
@@ -109,11 +113,11 @@
       // small chunks
       long size = 0;
       Address cur = addr.addOffsetTo( indexedFreeListField.getOffset() );
-      cur = cur.addOffsetTo(IndexSetStart*FreeList.sizeOf());
+      cur = cur.addOffsetTo(IndexSetStart*AdaptiveFreeList.sizeOf());
       for (int i=IndexSetStart; i<IndexSetSize; i += IndexSetStride) {
-         FreeList freeList = (FreeList) VMObjectFactory.newObject(FreeList.class, cur);
+         AdaptiveFreeList freeList = (AdaptiveFreeList) VMObjectFactory.newObject(AdaptiveFreeList.class, cur);
          size += i*freeList.count();
-         cur= cur.addOffsetTo(IndexSetStride*FreeList.sizeOf());
+         cur= cur.addOffsetTo(IndexSetStride*AdaptiveFreeList.sizeOf());
       }
 
       // large block
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * @(#)FreeList.java
- *
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-
-public class FreeList extends VMObject {
-   static {
-      VM.registerVMInitializedObserver(new Observer() {
-         public void update(Observable o, Object data) {
-            initialize(VM.getVM().getTypeDataBase());
-         }
-      });
-   }
-
-   private static synchronized void initialize(TypeDataBase db) {
-      Type type = db.lookupType("FreeList<FreeChunk>");
-      sizeField = type.getCIntegerField("_size");
-      countField = type.getCIntegerField("_count");
-      headerSize = type.getSize();
-   }
-
-   // Fields
-   private static CIntegerField sizeField;
-   private static CIntegerField countField;
-   private static long          headerSize;
-
-   //Constructor
-   public FreeList(Address address) {
-     super(address);
-   }
-
-   // Accessors
-   public long size() {
-      return sizeField.getValue(addr);
-   }
-
-   public long count() {
-      return  countField.getValue(addr);
-   }
-
-   public static long sizeOf() {
-     return headerSize;
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,6 +56,12 @@
   private static AddressField narrowKlassBaseField;
   private static CIntegerField narrowKlassShiftField;
 
+  public enum NARROW_OOP_MODE {
+    UnscaledNarrowOop,
+    ZeroBasedNarrowOop,
+    HeapBasedNarrowOop
+  }
+
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -94,7 +100,17 @@
 
   public Universe() {
   }
-
+  public static String narrowOopModeToString(NARROW_OOP_MODE mode) {
+    switch (mode) {
+    case UnscaledNarrowOop:
+      return "32-bits Oops";
+    case ZeroBasedNarrowOop:
+      return "zero based Compressed Oops";
+    case HeapBasedNarrowOop:
+      return "Compressed Oops with base";
+    }
+    return "";
+  }
   public CollectedHeap heap() {
     try {
       return (CollectedHeap) heapConstructor.instantiateWrapperFor(collectedHeapField.getValue());
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,10 @@
     layoutHelper = new IntField(type.getJIntField("_layout_helper"), 0);
     name         = type.getAddressField("_name");
     accessFlags  = new CIntField(type.getCIntegerField("_access_flags"), 0);
+    try {
+      traceIDField  = type.getField("_trace_id");
+    } catch(Exception e) {
+    }
     subklass     = new MetadataField(type.getAddressField("_subklass"), 0);
     nextSibling  = new MetadataField(type.getAddressField("_next_sibling"), 0);
 
@@ -86,6 +90,7 @@
   private static CIntField accessFlags;
   private static MetadataField  subklass;
   private static MetadataField  nextSibling;
+  private static sun.jvm.hotspot.types.Field traceIDField;
 
   private Address getValue(AddressField field) {
     return addr.getAddressAt(field.getOffset());
@@ -107,6 +112,11 @@
   public Klass    getSubklassKlass()    { return (Klass)    subklass.getValue(this);     }
   public Klass    getNextSiblingKlass() { return (Klass)    nextSibling.getValue(this);  }
 
+  public long traceID() {
+    if (traceIDField == null) return 0;
+    return traceIDField.getJLong(addr);
+  }
+
   // computed access flags - takes care of inner classes etc.
   // This is closer to actual source level than getAccessFlags() etc.
   public long computeModifierFlags() {
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,8 @@
   private static OopField threadNameField;
   private static OopField threadGroupField;
   private static LongField threadEETopField;
+  //tid field is new since 1.5
+  private static LongField threadTIDField;
   // threadStatus field is new since 1.5
   private static IntField threadStatusField;
   // parkBlocker field is new since 1.6
@@ -220,6 +222,7 @@
       threadNameField  = (OopField) k.findField("name", "[C");
       threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;");
       threadEETopField = (LongField) k.findField("eetop", "J");
+      threadTIDField = (LongField) k.findField("tid", "J");
       threadStatusField = (IntField) k.findField("threadStatus", "I");
       threadParkBlockerField = (OopField) k.findField("parkBlocker",
                                      "Ljava/lang/Object;");
@@ -268,6 +271,15 @@
     return VM.getVM().getThreads().createJavaThreadWrapper(addr);
   }
 
+  public static long threadOopGetTID(Oop threadOop) {
+    initThreadFields();
+    if (threadTIDField != null) {
+      return threadTIDField.getValue(threadOop);
+    } else {
+      return 0;
+    }
+  }
+
   /** returns value of java.lang.Thread.threadStatus field */
   public static int threadOopGetThreadStatus(Oop threadOop) {
     initThreadFields();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/opto/CompilerPhaseType.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.opto;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum CompilerPhaseType {
+  PHASE_BEFORE_STRINGOPTS ("Before StringOpts"),
+  PHASE_AFTER_STRINGOPTS ("After StringOpts"),
+  PHASE_BEFORE_REMOVEUSELESS ("Before RemoveUseless"),
+  PHASE_AFTER_PARSING ("After Parsing"),
+  PHASE_ITER_GVN1 ("Iter GVN 1"),
+  PHASE_PHASEIDEAL_BEFORE_EA ("PhaseIdealLoop before EA"),
+  PHASE_ITER_GVN_AFTER_EA ("Iter GVN after EA"),
+  PHASE_ITER_GVN_AFTER_ELIMINATION ("Iter GVN after eliminating allocations and locks"),
+  PHASE_PHASEIDEALLOOP1 ("PhaseIdealLoop 1"),
+  PHASE_PHASEIDEALLOOP2 ("PhaseIdealLoop 2"),
+  PHASE_PHASEIDEALLOOP3 ("PhaseIdealLoop 3"),
+  PHASE_CPP1 ("PhaseCPP 1"),
+  PHASE_ITER_GVN2 ("Iter GVN 2"),
+  PHASE_PHASEIDEALLOOP_ITERATIONS ("PhaseIdealLoop iterations"),
+  PHASE_OPTIMIZE_FINISHED ("Optimize finished"),
+  PHASE_GLOBAL_CODE_MOTION ("Global code motion"),
+  PHASE_FINAL_CODE ("Final Code"),
+  PHASE_AFTER_EA ("After Escape Analysis"),
+  PHASE_BEFORE_CLOOPS ("Before CountedLoop"),
+  PHASE_AFTER_CLOOPS ("After CountedLoop"),
+  PHASE_BEFORE_BEAUTIFY_LOOPS ("Before beautify loops"),
+  PHASE_AFTER_BEAUTIFY_LOOPS ("After beautify loops"),
+  PHASE_BEFORE_MATCHING ("Before Matching"),
+  PHASE_INCREMENTAL_INLINE ("Incremental Inline"),
+  PHASE_INCREMENTAL_BOXING_INLINE ("Incremental Boxing Inline"),
+  PHASE_END ("End"),
+  PHASE_FAILURE ("Failure"),
+  PHASE_NUM_TYPES ("Number of Phase Types");
+
+  private final String value;
+
+  CompilerPhaseType(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Flags.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum Flags {
+  // value origin
+  DEFAULT ("Default"),
+  COMMAND_LINE ("Command line"),
+  ENVIRON_VAR ("Environment variable"),
+  CONFIG_FILE ("Config file"),
+  MANAGEMENT ("Management"),
+  ERGONOMIC ("Ergonomic"),
+  ATTACH_ON_DEMAND ("Attach on demand"),
+  INTERNAL ("Internal");
+
+  private final String value;
+
+  Flags(String val) {
+    this.value = val;
+  }
+  public String value() {
+    return value;
+  }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
   private static AddressField currentPendingMonitorField;
   private static AddressField currentWaitingMonitorField;
 
+  private static JLongField allocatedBytesField;
+
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -61,6 +63,7 @@
     activeHandlesField = type.getAddressField("_active_handles");
     currentPendingMonitorField = type.getAddressField("_current_pending_monitor");
     currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor");
+    allocatedBytesField = type.getJLongField("_allocated_bytes");
   }
 
   public Thread(Address addr) {
@@ -104,6 +107,10 @@
     return new JNIHandleBlock(a);
   }
 
+  public long allocatedBytes() {
+    return allocatedBytesField.getValue(addr);
+  }
+
   public boolean   isVMThread()                { return false; }
   public boolean   isJavaThread()              { return false; }
   public boolean   isCompilerThread()          { return false; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VMOps.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum VMOps {
+  Dummy,
+  ThreadStop,
+  ThreadDump,
+  PrintThreads,
+  FindDeadlocks,
+  ForceSafepoint,
+  ForceAsyncSafepoint,
+  Deoptimize,
+  DeoptimizeFrame,
+  DeoptimizeAll,
+  ZombieAll,
+  UnlinkSymbols,
+  Verify,
+  PrintJNI,
+  HeapDumper,
+  DeoptimizeTheWorld,
+  CollectForMetadataAllocation,
+  GC_HeapInspection,
+  GenCollectFull,
+  GenCollectFullConcurrent,
+  GenCollectForAllocation,
+  ParallelGCFailedAllocation,
+  ParallelGCSystemGC,
+  CGC_Operation,
+  CMS_Initial_Mark,
+  CMS_Final_Remark,
+  G1CollectFull,
+  G1CollectForAllocation,
+  G1IncCollectionPause,
+  EnableBiasedLocking,
+  RevokeBias,
+  BulkRevokeBias,
+  PopulateDumpSharedSpace,
+  JNIFunctionTableCopier,
+  RedefineClasses,
+  GetOwnedMonitorInfo,
+  GetObjectMonitorUsage,
+  GetCurrentContendedMonitor,
+  GetStackTrace,
+  GetMultipleStackTraces,
+  GetAllStackTraces,
+  GetThreadListStackTraces,
+  GetFrameCount,
+  GetFrameLocation,
+  ChangeBreakpoints,
+  GetOrSetLocal,
+  GetCurrentLocation,
+  EnterInterpOnlyMode,
+  ChangeSingleStep,
+  HeapWalkOperation,
+  HeapIterateOperation,
+  ReportJavaOutOfMemory,
+  JFRCheckpoint,
+  Exit,
+  LinuxDllLoad,
+  Terminating
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/action/HSDBActionManager.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/action/HSDBActionManager.java	Wed Apr 22 06:24:15 2015 +0100
@@ -32,10 +32,12 @@
 public class HSDBActionManager extends ActionManager {
 
     public static ActionManager getInstance() {
-        if (manager == null) {
-            manager = new HSDBActionManager();
+        ActionManager m = ActionManager.getInstance();
+        if (m == null) {
+            m = new HSDBActionManager();
+            ActionManager.setInstance(m);
         }
-        return manager;
+        return m;
     }
 
     protected void addActions() {
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -799,6 +799,18 @@
         writeObjectID(klass.getJavaMirror());
 
         ClassData cd = (ClassData) classDataCache.get(klass);
+        if (cd == null) {
+            // The class is not present in the system dictionary, probably Lambda.
+            // Add it to cache here
+            if (klass instanceof InstanceKlass) {
+                InstanceKlass ik = (InstanceKlass) klass;
+                List fields = getInstanceFields(ik);
+                int instSize = getSizeForFields(fields);
+                cd = new ClassData(instSize, fields);
+                classDataCache.put(ik, cd);
+            }
+        }
+
         if (Assert.ASSERTS_ENABLED) {
             Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress());
         }
--- a/make/aix/makefiles/adlc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/aix/makefiles/adlc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -140,13 +140,7 @@
 # Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
 ADLCFLAGS += -q -T
 
-# Normally, debugging is done directly on the ad_<arch>*.cpp files.
-# But -g will put #line directives in those files pointing back to <arch>.ad.
-# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives
-# so skip it for 3.2 and ealier.
-ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
 ADLCFLAGS += -g
-endif
 
 ifdef LP64
 ADLCFLAGS += -D_LP64
--- a/make/aix/makefiles/ppc64.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/aix/makefiles/ppc64.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2012, 2013 SAP AG. All rights reserved.
+# Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2012, 2015 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
@@ -46,7 +46,9 @@
 #  - 1540-1090 (I) The destructor of "..." might not be called.
 #  - 1500-010: (W) WARNING in ...: Infinite loop.  Program may not stop.
 #    There are several infinite loops in the vm, suppress.
-CFLAGS += -qsuppress=1540-1090 -qsuppress=1500-010
+#  - 1540-1639 (I) The behavior of long type bit fields has changed ...
+#                  ... long type bit fields now default to long, not int.
+CFLAGS += -qsuppress=1540-1090 -qsuppress=1500-010 -qsuppress=1540-1639
 
 # Suppress 
 #  - 540-1088 (W) The exception specification is being ignored.
@@ -69,9 +71,6 @@
 OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
 OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
 
-# xlc 10.01 parameters for ipa compile.
-QIPA_COMPILE=$(if $(CXX_IS_V10),-qipa)
-
 # Xlc 10.1 parameters for aggressive optimization:
 # - qhot=level=1: Most aggressive loop optimizations.
 # - qignerrno: Assume errno is not modified by system calls.
@@ -86,7 +85,7 @@
 OPT_CFLAGS/synchronizer.o = $(OPT_CFLAGS) -qnoinline
 
 # Set all the xlC V10.1 options here.
-OPT_CFLAGS += $(QIPA_COMPILE) $(QV10_OPT) $(QV10_OPT_AGGRESSIVE)
+OPT_CFLAGS += $(QV10_OPT) $(QV10_OPT_AGGRESSIVE)
 
 export OBJECT_MODE=64
 
--- a/make/aix/makefiles/xlc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/aix/makefiles/xlc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2012, 2013 SAP. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2015 SAP. All rights reserved.
 # 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,13 +34,17 @@
 
 AS  = $(CC) -c
 
-# get xlc version
-CXX_VERSION   := $(shell $(CXX) -qversion 2>&1 | sed -n 's/.*Version: \([0-9.]*\)/\1/p')
+# get xlc version which comes as VV.RR.MMMM.LLLL where 'VV' is the version,
+# 'RR' is the release, 'MMMM' is the modification and 'LLLL' is the level.
+# We only use 'VV.RR.LLLL' to avoid integer overflows in bash when comparing
+# the version numbers (some shells only support 32-bit integer compares!).
+CXX_VERSION := $(shell $(CXX) -qversion 2>&1 | \
+                   sed -n 's/.*Version: \([0-9]\{2\}\).\([0-9]\{2\}\).[0-9]\{4\}.\([0-9]\{4\}\)/\1\2\3/p')
 
 # xlc 08.00.0000.0023 and higher supports -qtune=balanced
-CXX_SUPPORTS_BALANCED_TUNING=$(shell if [ $(subst .,,$(CXX_VERSION)) -ge 080000000023 ] ; then echo "true" ; fi)
+CXX_SUPPORTS_BALANCED_TUNING := $(shell if [ $(CXX_VERSION) -ge 08000023 ] ; then echo "true" ; fi)
 # xlc 10.01 is used with aggressive optimizations to boost performance
-CXX_IS_V10=$(shell if [ $(subst .,,$(CXX_VERSION)) -ge 100100000000 ] ; then echo "true" ; fi)
+CXX_IS_V10 := $(shell if [ $(CXX_VERSION) -ge 10010000 ] ; then echo "true" ; fi)
 
 # check for precompiled headers support
 
@@ -74,6 +78,12 @@
 # no xlc counterpart for -fcheck-new
 # CFLAGS += -fcheck-new
 
+# We need to define this on the command line if we want to use the the
+# predefined format specifiers from "inttypes.h". Otherwise system headrs
+# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS
+# in globalDefinitions.hpp
+CFLAGS += -D__STDC_FORMAT_MACROS
+
 ARCHFLAG = -q64
 
 CFLAGS     += $(ARCHFLAG)
@@ -124,7 +134,7 @@
 # MAPFLAG = -Xlinker --version-script=FILENAME
 
 # Build shared library
-SHARED_FLAG = -q64 -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath
+SHARED_FLAG = -q64 -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath -bernotok
 
 #------------------------------------------------------------------------
 # Debug flags
--- a/make/bsd/makefiles/gcc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/bsd/makefiles/gcc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -349,7 +349,7 @@
   # 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)
+  LFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN)
 endif
 
 
--- a/make/bsd/makefiles/sa.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/bsd/makefiles/sa.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
 
 include $(GAMMADIR)/make/sa.files
 
+-include $(HS_ALT_MAKE)/bsd/makefiles/sa.make
+
 TOPDIR    = $(shell echo `pwd`)
 GENERATED = $(TOPDIR)/../generated
 
--- a/make/bsd/makefiles/saproc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/bsd/makefiles/saproc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -64,9 +64,22 @@
 else
   ifeq ($(OS_VENDOR), Darwin)
     SASRCFILES = $(DARWIN_NON_STUB_SASRCFILES)
-    SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
+    SALIBS = -g \
+             -framework Foundation \
+             -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))
+
+    # This is needed to locate JavaNativeFoundation.framework
+    # JDK 8 doesn't have SYSROOT_CFLAGS, so we'll cobble it together here
+    SA_SYSROOT_FLAGS=
+    ifneq ($(SDKPATH),)
+      SA_SYSROOT_FLAGS += -isysroot "$(SDKPATH)" -iframework"$(SDKPATH)/System/Library/Frameworks"
+    endif
+    # always needed, even if SDKPATH is empty
+    SA_SYSROOT_FLAGS += -F"$(SDKPATH)/System/Library/Frameworks/JavaVM.framework/Frameworks"
   else
     SASRCFILES = $(SASRCDIR)/StubDebuggerLocal.c
     SALIBS = 
@@ -97,17 +110,14 @@
 
 ifneq ($(OS_VENDOR), Darwin)
 SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE))
+else
+# bring in minimum version argument or we'll fail on OSX 10.10
+SA_LFLAGS = $(LFLAGS)
 endif
 SA_LFLAGS += $(LDFLAGS_HASH_STYLE)
 
-ifeq ($(OS_VENDOR), Darwin)
-  BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \
-    -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") \
-    -I/System/Library/Frameworks/JavaVM.framework/Headers
-else
-  BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \
-    -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
-endif
+BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \
+  -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
 
 $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE)
 	$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
@@ -116,6 +126,7 @@
 	fi
 	@echo Making SA debugger back-end...
 	$(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE                   \
+	           $(SA_SYSROOT_FLAGS)                                  \
 	           $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG)       \
 	           -I$(SASRCDIR)                                        \
 	           -I$(GENERATED)                                       \
--- a/make/defs.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/defs.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -273,7 +273,7 @@
 
   # Use uname output for SRCARCH, but deal with platform differences. If ARCH
   # is not explicitly listed below, it is treated as x86.
-  SRCARCH     = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc ppc64 zero,$(ARCH)))
+  SRCARCH    ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc64 zero,$(ARCH)))
   ARCH/       = x86
   ARCH/sparc  = sparc
   ARCH/sparc64= sparc
@@ -281,12 +281,10 @@
   ARCH/amd64  = x86
   ARCH/x86_64 = x86
   ARCH/ppc64  = ppc
-  ARCH/ppc    = ppc
-  ARCH/arm    = arm
   ARCH/zero   = zero
 
   # BUILDARCH is usually the same as SRCARCH, except for sparcv9
-  BUILDARCH = $(SRCARCH)
+  BUILDARCH ?= $(SRCARCH)
   ifeq ($(BUILDARCH), x86)
     ifdef LP64
       BUILDARCH = amd64
@@ -306,18 +304,16 @@
   endif
 
   # LIBARCH is 1:1 mapping from BUILDARCH
-  LIBARCH         = $(LIBARCH/$(BUILDARCH))
+  LIBARCH        ?= $(LIBARCH/$(BUILDARCH))
   LIBARCH/i486    = i386
   LIBARCH/amd64   = amd64
   LIBARCH/sparc   = sparc
   LIBARCH/sparcv9 = sparcv9
   LIBARCH/ia64    = ia64
   LIBARCH/ppc64   = ppc64
-  LIBARCH/ppc     = ppc
-  LIBARCH/arm     = arm
   LIBARCH/zero    = $(ZERO_LIBARCH)
 
-  LP64_ARCH = sparcv9 amd64 ia64 ppc64 zero
+  LP64_ARCH += sparcv9 amd64 ia64 ppc64 zero
 endif
 
 # Required make macro settings for all platforms
--- a/make/hotspot_version	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/hotspot_version	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 # 
-# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,11 +31,11 @@
 #
 
 # Don't put quotes (fail windows build).
-HOTSPOT_VM_COPYRIGHT=Copyright 2014
+HOTSPOT_VM_COPYRIGHT=Copyright 2015
 
 HS_MAJOR_VER=25
-HS_MINOR_VER=40
-HS_BUILD_NUMBER=23
+HS_MINOR_VER=60
+HS_BUILD_NUMBER=12
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/linux/makefiles/arm.make	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-#
-# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#  
-#
-
-Obj_Files += linux_arm.o
-
-ifneq ($(EXT_LIBS_PATH),)
-  LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a 
-endif
-
-CFLAGS += -DVM_LITTLE_ENDIAN
--- a/make/linux/makefiles/build_vm_def.sh	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-# If we're cross compiling use that path for nm
-if [ "$CROSS_COMPILE_ARCH" != "" ]; then 
-NM=$ALT_COMPILER_PATH/nm
-else
-NM=nm
-fi
-
-$NM --defined-only $* \
-    | awk '{
-              if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";"
-              if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";"
-              if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";"
-          }' \
-    | sort -u
--- a/make/linux/makefiles/buildtree.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/linux/makefiles/buildtree.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -70,6 +70,8 @@
     PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc
   else
     PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH)
+    ALT_PLATFORM_FILE = $(HS_ALT_MAKE)/$(OS_FAMILY)/platform_$(BUILDARCH)
+    PLATFORM_FILE := $(if $(wildcard $(ALT_PLATFORM_FILE)),$(ALT_PLATFORM_FILE),$(PLATFORM_FILE))
   endif
 endif
 
@@ -202,7 +204,7 @@
 	$(QUIETLY) ( \
 	$(BUILDTREE_COMMENT); \
 	echo; \
-	echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \
+	echo "Platform_file = $(PLATFORM_FILE)" | sed -e 's|$(HS_ALT_MAKE)|$$(HS_ALT_MAKE)|' -e 's|$(GAMMADIR)|$$(GAMMADIR)|'; \
 	sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \
 	echo; \
 	echo "GAMMADIR = $(GAMMADIR)"; \
--- a/make/linux/makefiles/defs.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/linux/makefiles/defs.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -109,22 +109,6 @@
   HS_ARCH          = x86
 endif
 
-# ARM
-ifeq ($(ARCH), arm)
-  ARCH_DATA_MODEL  = 32
-  PLATFORM         = linux-arm
-  VM_PLATFORM      = linux_arm
-  HS_ARCH          = arm
-endif
-
-# PPC
-ifeq ($(ARCH), ppc)
-  ARCH_DATA_MODEL  = 32
-  PLATFORM         = linux-ppc
-  VM_PLATFORM      = linux_ppc
-  HS_ARCH          = ppc
-endif
-
 # PPC64
 ifeq ($(ARCH), ppc64)
   ARCH_DATA_MODEL  = 64
--- a/make/linux/makefiles/gcc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/linux/makefiles/gcc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -176,11 +176,7 @@
 ARCHFLAG/ia64    =
 ARCHFLAG/sparc   = -m32 -mcpu=v9
 ARCHFLAG/sparcv9 = -m64 -mcpu=v9
-ARCHFLAG/arm     =  -fsigned-char
 ARCHFLAG/zero    = $(ZERO_ARCHFLAG)
-ifndef E500V2
-ARCHFLAG/ppc     =  -mcpu=powerpc
-endif
 ARCHFLAG/ppc64   =  -m64
 
 CFLAGS     += $(ARCHFLAG)
@@ -188,10 +184,6 @@
 LFLAGS     += $(ARCHFLAG)
 ASFLAGS    += $(ARCHFLAG)
 
-ifdef E500V2
-CFLAGS += -DE500V2
-endif
-
 # Use C++ Interpreter
 ifdef CC_INTERP
   CFLAGS += -DCC_INTERP
@@ -345,49 +337,43 @@
   # Note: The Itanium gcc compiler crashes when using -gstabs.
   DEBUG_CFLAGS/ia64  = -g
   DEBUG_CFLAGS/amd64 = -g
-  DEBUG_CFLAGS/arm   = -g
-  DEBUG_CFLAGS/ppc   = -g
   DEBUG_CFLAGS/ppc64 = -g
   DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
   ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
         # Clang doesn't understand -gstabs
-        DEBUG_CFLAGS += -g
+        DEBUG_CFLAGS/$(BUILDARCH) = -g
       else
-        DEBUG_CFLAGS += -gstabs
+        DEBUG_CFLAGS/$(BUILDARCH) = -gstabs
       endif
   endif
   
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     FASTDEBUG_CFLAGS/ia64  = -g
     FASTDEBUG_CFLAGS/amd64 = -g
-    FASTDEBUG_CFLAGS/arm   = -g
-    FASTDEBUG_CFLAGS/ppc   = -g
     FASTDEBUG_CFLAGS/ppc64 = -g
     FASTDEBUG_CFLAGS/zero  = -g
-    FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
+    FASTDEBUG_CFLAGS += $(FASTDEBUG_CFLAGS/$(BUILDARCH))
     ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
         # Clang doesn't understand -gstabs
-        FASTDEBUG_CFLAGS += -g
+        FASTDEBUG_CFLAGS/$(BUILDARCH) = -g
       else
-        FASTDEBUG_CFLAGS += -gstabs
+        FASTDEBUG_CFLAGS/$(BUILDARCH) = -gstabs
       endif
     endif
   
     OPT_CFLAGS/ia64  = -g
     OPT_CFLAGS/amd64 = -g
-    OPT_CFLAGS/arm   = -g
-    OPT_CFLAGS/ppc   = -g
     OPT_CFLAGS/ppc64 = -g
     OPT_CFLAGS/zero  = -g
     OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH))
     ifeq ($(OPT_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
         # Clang doesn't understand -gstabs
-        OPT_CFLAGS += -g
+        OPT_CFLAGS/$(BUILDARCH) = -g
       else
-        OPT_CFLAGS += -gstabs
+        OPT_CFLAGS/$(BUILDARCH) = -gstabs
       endif
     endif
   endif
@@ -411,3 +397,5 @@
 ifndef USE_SUNCC
   CFLAGS += -fno-omit-frame-pointer
 endif
+
+-include $(HS_ALT_MAKE)/linux/makefiles/gcc.make
--- a/make/linux/makefiles/ppc.make	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#
-# Copyright (c) 2004, 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.
-#  
-#
-
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-
-# Must also specify if CPU is big endian
-CFLAGS += -DVM_BIG_ENDIAN
-
-ifdef E500V2
-ASFLAGS += -Wa,-mspe -Wa,--defsym -Wa,E500V2=1 
-endif
--- a/make/linux/makefiles/saproc.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/linux/makefiles/saproc.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -69,19 +69,21 @@
 endif
 
 ifneq ($(ALT_SASRCDIR),)
-ALT_SAINCDIR=-I$(ALT_SASRCDIR)
+ALT_SAINCDIR=-I$(ALT_SASRCDIR) -DALT_SASRCDIR
 else
 ALT_SAINCDIR=
 endif
 SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) $(LDFLAGS_HASH_STYLE)
 
+SAARCH ?= $(BUILDARCH)
+
 $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE)
 	$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
 	  echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
 	  exit 1; \
 	fi
 	@echo Making SA debugger back-end...
-	$(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE                   \
+	$(QUIETLY) $(CC) -D$(SAARCH) -D_GNU_SOURCE                      \
 		   -D_FILE_OFFSET_BITS=64                               \
                    $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG)     \
 	           -I$(SASRCDIR)                                        \
--- a/make/linux/makefiles/vm.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/linux/makefiles/vm.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,8 +45,9 @@
 ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   include $(MAKEFILES_DIR)/zeroshark.make
 else
-  include $(MAKEFILES_DIR)/$(BUILDARCH).make
-  -include $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make
+  BUILDARCH_MAKE = $(MAKEFILES_DIR)/$(BUILDARCH).make
+  ALT_BUILDARCH_MAKE = $(HS_ALT_MAKE)/$(Platform_os_family)/makefiles/$(BUILDARCH).make
+  include $(if $(wildcard $(ALT_BUILDARCH_MAKE)),$(ALT_BUILDARCH_MAKE),$(BUILDARCH_MAKE))
 endif
 
 # set VPATH so make knows where to look for source files
@@ -245,8 +246,14 @@
 	rm -f $@
 	cat $^ > $@
 
+VMDEF_PAT  = ^_ZTV
+VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT)
+VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT)
+VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT)
+
 vm.def: $(Res_Files) $(Obj_Files)
-	sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
+	$(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \
+	awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@
 
 mapfile_ext:
 	rm -f $@
--- a/make/linux/platform_arm	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-os_family = linux
-
-arch = arm
-
-arch_model = arm
-
-os_arch = linux_arm
-
-os_arch_model = linux_arm
-
-lib_arch = arm
-
-compiler = gcc
-
-gnu_dis_arch = arm
-
-sysdefs = -DLINUX -D_GNU_SOURCE -DARM
--- a/make/linux/platform_ppc	Fri Feb 27 09:59:29 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-os_family = linux
-
-arch = ppc
-
-arch_model = ppc_32
-
-os_arch = linux_ppc
-
-os_arch_model = linux_ppc_32
-
-lib_arch = ppc
-
-compiler = gcc
-
-gnu_dis_arch = ppc
-
-sysdefs = -DLINUX -D_GNU_SOURCE -DPPC32
--- a/make/solaris/makefiles/sa.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/solaris/makefiles/sa.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,12 @@
 # and generate JNI header file for native methods.
 
 include $(GAMMADIR)/make/solaris/makefiles/rules.make
+include $(GAMMADIR)/make/defs.make
 AGENT_DIR = $(GAMMADIR)/agent
 include $(GAMMADIR)/make/sa.files
+
+-include $(HS_ALT_MAKE)/solaris/makefiles/sa.make
+
 GENERATED = ../generated
 
 # tools.jar is needed by the JDI - SA binding
--- a/make/windows/makefiles/sa.make	Fri Feb 27 09:59:29 2015 +0000
+++ b/make/windows/makefiles/sa.make	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,22 @@
 
 GENERATED = ../generated
 
+HS_COMMON_SRC_REL = src
+
+!if "$(OPENJDK)" != "true"
+HS_ALT_SRC_REL=src/closed
+HS_ALT_SRC = $(WorkSpace)/$(HS_ALT_SRC_REL)
+!ifndef HS_ALT_MAKE
+HS_ALT_MAKE=$(WorkSpace)/make/closed
+!endif
+!endif
+
+HS_COMMON_SRC = $(WorkSpace)/$(HS_COMMON_SRC_REL)
+
+!ifdef HS_ALT_MAKE
+!include $(HS_ALT_MAKE)/windows/makefiles/sa.make
+!endif
+
 # tools.jar is needed by the JDI - SA binding
 SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
 
--- a/src/cpu/ppc/vm/frame_ppc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/ppc/vm/frame_ppc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -318,3 +318,10 @@
   // unused... but returns fp() to minimize changes introduced by 7087445
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) {
+  find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp
+}
+#endif
--- a/src/cpu/ppc/vm/ppc.ad	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/ppc/vm/ppc.ad	Wed Apr 22 06:24:15 2015 +0100
@@ -4418,11 +4418,11 @@
   interface(CONST_INTER);
 %}
 
-// constant 'float +0.0'.
+// Float Immediate: +0.0f.
 operand immF_0() %{
-  predicate((n->getf() == 0) &&
-            (fpclassify(n->getf()) == FP_ZERO) && (signbit(n->getf()) == 0));
+  predicate(jint_cast(n->getf()) == 0);
   match(ConF);
+  
   op_cost(0);
   format %{ %}
   interface(CONST_INTER);
--- a/src/cpu/sparc/vm/frame_sparc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/frame_sparc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -342,7 +342,7 @@
 // constructors
 
 // Construct an unpatchable, deficient frame
-frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) {
+void frame::init(intptr_t* sp, address pc, CodeBlob* cb) {
 #ifdef _LP64
   assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp");
 #endif
@@ -364,6 +364,10 @@
 #endif // ASSERT
 }
 
+frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) {
+  init(sp, pc, cb);
+}
+
 frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) :
   _sp(sp),
   _younger_sp(younger_sp),
@@ -418,6 +422,13 @@
   }
 }
 
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  init((intptr_t*)sp, (address)pc, NULL);
+}
+#endif
+
 bool frame::is_interpreted_frame() const  {
   return Interpreter::contains(pc());
 }
--- a/src/cpu/sparc/vm/frame_sparc.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/frame_sparc.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -164,6 +164,8 @@
   enum unpatchable_t { unpatchable };
   frame(intptr_t* sp, unpatchable_t, address pc = NULL, CodeBlob* cb = NULL);
 
+  void init(intptr_t* sp, address pc, CodeBlob* cb);
+
   // Walk from sp outward looking for old_sp, and return old_sp's predecessor
   // (i.e. return the sp from the frame where old_sp is the fp).
   // Register windows are assumed to be flushed for the stack in question.
--- a/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -630,7 +630,12 @@
 
 inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) {
   relocate(a.rspec(offset));
-  ldf(w, a.base(), a.disp() + offset, d);
+  if (a.has_index()) {
+    assert(offset == 0, "");
+    ldf(w, a.base(), a.index(), d);
+  } else {
+    ldf(w, a.base(), a.disp() + offset, d);
+  }
 }
 
 // returns if membar generates anything, obviously this code should mirror
--- a/src/cpu/sparc/vm/sparc.ad	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/sparc.ad	Wed Apr 22 06:24:15 2015 +0100
@@ -3760,13 +3760,9 @@
   interface(CONST_INTER);
 %}
 
+// Double Immediate: +0.0d
 operand immD0() %{
-#ifdef _LP64
-  // on 64-bit architectures this comparision is faster
   predicate(jlong_cast(n->getd()) == 0);
-#else
-  predicate((n->getd() == 0) && (fpclass(n->getd()) == FP_PZERO));
-#endif
   match(ConD);
 
   op_cost(0);
@@ -3783,9 +3779,9 @@
   interface(CONST_INTER);
 %}
 
-// Float Immediate: 0
-operand immF0() %{
-  predicate((n->getf() == 0) && (fpclass(n->getf()) == FP_PZERO));
+// Float Immediate: +0.0f
+operand immF0() %{ 
+  predicate(jint_cast(n->getf()) == 0);  
   match(ConF);
 
   op_cost(0);
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -37,7 +37,7 @@
 
 int VM_Version::_features = VM_Version::unknown_m;
 const char* VM_Version::_features_str = "";
-unsigned int VM_Version::_L2_cache_line_size = 0;
+unsigned int VM_Version::_L2_data_cache_line_size = 0;
 
 void VM_Version::initialize() {
   _features = determine_features();
@@ -363,7 +363,7 @@
 
 #ifndef PRODUCT
   if (PrintMiscellaneous && Verbose) {
-    tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
+    tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size());
     tty->print("Allocation");
     if (AllocatePrefetchStyle <= 0) {
       tty->print_cr(": no prefetching");
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -96,8 +96,8 @@
   static int  _features;
   static const char* _features_str;
 
-  static unsigned int _L2_cache_line_size;
-  static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
+  static unsigned int _L2_data_cache_line_size;
+  static unsigned int L2_data_cache_line_size() { return _L2_data_cache_line_size; }
 
   static void print_features();
   static int  determine_features();
@@ -171,7 +171,7 @@
   static const char* cpu_features()     { return _features_str; }
 
   // default prefetch block size on sparc
-  static intx prefetch_data_size()      { return L2_cache_line_size();  }
+  static intx prefetch_data_size()      { return L2_data_cache_line_size();  }
 
   // Prefetch
   static intx prefetch_copy_interval_in_bytes() {
--- a/src/cpu/x86/vm/frame_x86.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/x86/vm/frame_x86.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -717,3 +717,10 @@
   assert(! is_compiled_frame(), "unknown compiled frame size");
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
+}
+#endif
--- a/src/cpu/x86/vm/frame_x86.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/x86/vm/frame_x86.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -187,6 +187,8 @@
 
   frame(intptr_t* sp, intptr_t* fp);
 
+  void init(intptr_t* sp, intptr_t* fp, address pc);
+
   // accessors for the instance variables
   // Note: not necessarily the real 'frame pointer' (see real_fp)
   intptr_t*   fp() const { return _fp; }
--- a/src/cpu/x86/vm/frame_x86.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/x86/vm/frame_x86.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -40,7 +40,7 @@
   _deopt_state = unknown;
 }
 
-inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
+inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
   _sp = sp;
   _unextended_sp = sp;
   _fp = fp;
@@ -58,6 +58,10 @@
   }
 }
 
+inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
+  init(sp, fp, pc);
+}
+
 inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
   _sp = sp;
   _unextended_sp = unextended_sp;
--- a/src/cpu/x86/vm/vm_version_x86.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/x86/vm/vm_version_x86.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -570,10 +570,12 @@
   static uint cores_per_cpu()  {
     uint result = 1;
     if (is_intel()) {
-      if (supports_processor_topology()) {
+      bool supports_topology = supports_processor_topology();
+      if (supports_topology) {
         result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
                  _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
-      } else {
+      }
+      if (!supports_topology || result == 0) {
         result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
       }
     } else if (is_amd()) {
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -758,7 +758,7 @@
     if (method->is_static())
       object = method->constants()->pool_holder()->java_mirror();
     else
-      object = (oop) locals[0];
+      object = (oop) (void*)locals[0];
     monitor->set_obj(object);
   }
 
--- a/src/cpu/zero/vm/frame_zero.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/zero/vm/frame_zero.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -441,3 +441,10 @@
   // unused... but returns fp() to minimize changes introduced by 7087445
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  Unimplemented();
+}
+#endif
--- a/src/cpu/zero/vm/frame_zero.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/zero/vm/frame_zero.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -26,6 +26,8 @@
 #ifndef CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
 #define CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
 
+#include "code/codeCache.hpp"
+
 // Constructors
 
 inline frame::frame() {
--- a/src/cpu/zero/vm/stack_zero.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/zero/vm/stack_zero.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -30,7 +30,9 @@
 
 int ZeroStack::suggest_size(Thread *thread) const {
   assert(needs_setup(), "already set up");
-  return align_size_down(abi_stack_available(thread) / 2, wordSize);
+  int abi_available = abi_stack_available(thread);
+  assert(abi_available >= 0, "available abi stack must be >= 0");
+  return align_size_down(abi_available / 2, wordSize);
 }
 
 void ZeroStack::handle_overflow(TRAPS) {
--- a/src/cpu/zero/vm/stack_zero.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/cpu/zero/vm/stack_zero.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -48,9 +48,11 @@
 // to use under normal circumstances.  Note that the returned
 // value can be negative.
 inline int ZeroStack::abi_stack_available(Thread *thread) const {
-  int stack_used = thread->stack_base() - (address) &stack_used;
+  guarantee(Thread::current() == thread, "should run in the same thread");
+  int stack_used = thread->stack_base() - (address) &stack_used
+    + (StackYellowPages+StackRedPages+StackShadowPages) * os::vm_page_size();
   int stack_free = thread->stack_size() - stack_used;
-  return stack_free - shadow_pages_size();
+  return stack_free;
 }
 
 #endif // CPU_ZERO_VM_STACK_ZERO_INLINE_HPP
--- a/src/os/aix/vm/os_aix.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/aix/vm/os_aix.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -3987,11 +3987,6 @@
   return JNI_OK;
 }
 
-// this is called at the end of vm_initialization
-void os::init_3(void) {
-  return;
-}
-
 // Mark the polling page as unreadable
 void os::make_polling_page_unreadable(void) {
   if (!guard_memory((char*)_polling_page, Aix::page_size())) {
--- a/src/os/aix/vm/perfMemory_aix.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/aix/vm/perfMemory_aix.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -31,6 +31,7 @@
 #include "os_aix.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/perfMemory.hpp"
+#include "services/memTracker.hpp"
 #include "utilities/exceptions.hpp"
 
 // put OS-includes here
@@ -196,12 +197,37 @@
   return pid;
 }
 
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+static bool is_statbuf_secure(struct stat *statp) {
+  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+    // The path represents a link or some non-directory file type,
+    // which is not what we expected. Declare it insecure.
+    //
+    return false;
+  }
+  // We have an existing directory, check if the permissions are safe.
+  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+    // The directory is open for writing and could be subjected
+    // to a symlink or a hard link attack. Declare it insecure.
+    return false;
+  }
+  // See if the uid of the directory matches the effective uid of the process.
+  //
+  if (statp->st_uid != geteuid()) {
+    // The directory was not created by this user, declare it insecure.
+    return false;
+  }
+  return true;
+}
 
-// check if the given path is considered a secure directory for
+
+// Check if the given path is considered a secure directory for
 // the backing store files. Returns true if the directory exists
 // and is considered a secure location. Returns false if the path
 // is a symbolic link or if an error occurred.
-//
 static bool is_directory_secure(const char* path) {
   struct stat statbuf;
   int result = 0;
@@ -211,38 +237,276 @@
     return false;
   }
 
-  // the path exists, now check it's mode
-  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
-    // the path represents a link or some non-directory file type,
-    // which is not what we expected. declare it insecure.
-    //
+  // The path exists, see if it is secure.
+  return is_statbuf_secure(&statbuf);
+}
+
+// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+static bool is_dirfd_secure(int dir_fd) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // The path exists, now check its mode.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+static bool is_same_fsobject(int fd1, int fd2) {
+  struct stat statbuf1;
+  struct stat statbuf2;
+  int result = 0;
+
+  RESTARTABLE(::fstat(fd1, &statbuf1), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+  RESTARTABLE(::fstat(fd2, &statbuf2), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  if ((statbuf1.st_ino == statbuf2.st_ino) &&
+      (statbuf1.st_dev == statbuf2.st_dev)) {
+    return true;
+  } else {
     return false;
   }
-  else {
-    // we have an existing directory, check if the permissions are safe.
-    //
-    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
-      // the directory is open for writing and could be subjected
-      // to a symlnk attack. declare it insecure.
-      //
-      return false;
+}
+
+// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
+// We use the jdk6 implementation here.
+#ifndef O_NOFOLLOW
+// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
+// was done in jdk 5/6 hotspot by Oracle this way
+static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
+  struct stat orig_st;
+  struct stat new_st;
+  bool create;
+  int error;
+  int fd;
+
+  create = false;
+
+  if (lstat(path, &orig_st) != 0) {
+    if (errno == ENOENT && (oflag & O_CREAT) != 0) {
+      // File doesn't exist, but_we want to create it, add O_EXCL flag
+      // to make sure no-one creates it (or a symlink) before us
+      // This works as we expect with symlinks, from posix man page:
+      // 'If O_EXCL  and  O_CREAT  are set, and path names a symbolic
+      // link, open() shall fail and set errno to [EEXIST]'.
+      oflag |= O_EXCL;
+      create = true;
+    } else {
+      // File doesn't exist, and we are not creating it.
+      return OS_ERR;
+    }
+  } else {
+    // Lstat success, check if existing file is a link.
+    if ((orig_st.st_mode & S_IFMT) == S_IFLNK)  {
+      // File is a symlink.
+      errno = ELOOP;
+      return OS_ERR;
+    }
+  }
+
+  if (use_mode == true) {
+    fd = open(path, oflag, mode);
+  } else {
+    fd = open(path, oflag);
+  }
+
+  if (fd == OS_ERR) {
+    return fd;
+  }
+
+  // Can't do inode checks on before/after if we created the file.
+  if (create == false) {
+    if (fstat(fd, &new_st) != 0) {
+      // Keep errno from fstat, in case close also fails.
+      error = errno;
+      ::close(fd);
+      errno = error;
+      return OS_ERR;
+    }
+
+    if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
+      // File was tampered with during race window.
+      ::close(fd);
+      errno = EEXIST;
+      if (PrintMiscellaneous && Verbose) {
+        warning("possible file tampering attempt detected when opening %s", path);
+      }
+      return OS_ERR;
     }
   }
+
+  return fd;
+}
+
+static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
+  return open_o_nofollow_impl(path, oflag, mode, true);
+}
+
+static int open_o_nofollow(const char* path, int oflag) {
+  return open_o_nofollow_impl(path, oflag, 0, false);
+}
+#endif
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+static DIR *open_directory_secure(const char* dirname) {
+  // Open the directory using open() so that it can be verified
+  // to be secure by calling is_dirfd_secure(), opendir() and then check
+  // to see if they are the same file system object.  This method does not
+  // introduce a window of opportunity for the directory to be attacked that
+  // calling opendir() and is_directory_secure() does.
+  int result;
+  DIR *dirp = NULL;
+
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+#else
+  // workaround (jdk6 coding)
+  RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
+#endif
+
+  if (result == OS_ERR) {
+    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+    if (PrintMiscellaneous && Verbose) {
+      if (errno == ELOOP) {
+        warning("directory %s is a symlink and is not secure\n", dirname);
+      } else {
+        warning("could not open directory %s: %s\n", dirname, strerror(errno));
+      }
+    }
+    return dirp;
+  }
+  int fd = result;
+
+  // Determine if the open directory is secure.
+  if (!is_dirfd_secure(fd)) {
+    // The directory is not a secure directory.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Open the directory.
+  dirp = ::opendir(dirname);
+  if (dirp == NULL) {
+    // The directory doesn't exist, close fd and return.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Check to make sure fd and dirp are referencing the same file system object.
+  if (!is_same_fsobject(fd, dirp->dd_fd)) {
+    // The directory is not secure.
+    os::close(fd);
+    os::closedir(dirp);
+    dirp = NULL;
+    return dirp;
+  }
+
+  // Close initial open now that we know directory is secure
+  os::close(fd);
+
+  return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions.  Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+  // Open the directory.
+  DIR* dirp = open_directory_secure(dirname);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+    return dirp;
+  }
+  int fd = dirp->dd_fd;
+
+  // Open a fd to the cwd and save it off.
+  int result;
+  RESTARTABLE(::open(".", O_RDONLY), result);
+  if (result == OS_ERR) {
+    *saved_cwd_fd = -1;
+  } else {
+    *saved_cwd_fd = result;
+  }
+
+  // Set the current directory to dirname by using the fd of the directory.
+  result = fchdir(fd);
+
+  return dirp;
+}
+
+// Close the directory and restore the current working directory.
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+  int result;
+  // If we have a saved cwd change back to it and close the fd.
+  if (saved_cwd_fd != -1) {
+    result = fchdir(saved_cwd_fd);
+    ::close(saved_cwd_fd);
+  }
+
+  // Close the directory.
+  os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+static bool is_file_secure(int fd, const char *filename) {
+
+  int result;
+  struct stat statbuf;
+
+  // Determine if the file is secure.
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed on %s: %s\n", filename, strerror(errno));
+    }
+    return false;
+  }
+  if (statbuf.st_nlink > 1) {
+    // A file with multiple links is not expected.
+    if (PrintMiscellaneous && Verbose) {
+      warning("file %s has multiple links\n", filename);
+    }
+    return false;
+  }
   return true;
 }
 
-
-// return the user name for the given user id
+// Return the user name for the given user id.
 //
-// the caller is expected to free the allocated memory.
-//
+// The caller is expected to free the allocated memory.
 static char* get_user_name(uid_t uid) {
 
   struct passwd pwent;
 
-  // determine the max pwbuf size from sysconf, and hardcode
+  // Determine the max pwbuf size from sysconf, and hardcode
   // a default if this not available through sysconf.
-  //
   long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
   if (bufsize == -1)
     bufsize = 1024;
@@ -344,7 +608,8 @@
     strcat(usrdir_name, "/");
     strcat(usrdir_name, dentry->d_name);
 
-    DIR* subdirp = os::opendir(usrdir_name);
+    // Open the user directory.
+    DIR* subdirp = open_directory_secure(usrdir_name);
 
     if (subdirp == NULL) {
       FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
@@ -464,28 +729,7 @@
   }
 }
 
-
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
-  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
-  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
-  strcpy(path, dirname);
-  strcat(path, "/");
-  strcat(path, filename);
-
-  remove_file(path);
-
-  FREE_C_HEAP_ARRAY(char, path, mtInternal);
-}
-
-
-// cleanup stale shared memory resources
+// Cleanup stale shared memory resources
 //
 // This method attempts to remove all stale shared memory files in
 // the named user temporary directory. It scans the named directory
@@ -493,32 +737,26 @@
 // process id is extracted from the file name and a test is run to
 // determine if the process is alive. If the process is not alive,
 // any stale file resources are removed.
-//
 static void cleanup_sharedmem_resources(const char* dirname) {
 
-  // open the user temp directory
-  DIR* dirp = os::opendir(dirname);
-
+  int saved_cwd_fd;
+  // Open the directory.
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   if (dirp == NULL) {
-    // directory doesn't exist, so there is nothing to cleanup
+     // Directory doesn't exist or is insecure, so there is nothing to cleanup.
     return;
   }
 
-  if (!is_directory_secure(dirname)) {
-    // the directory is not a secure directory
-    return;
-  }
-
-  // for each entry in the directory that matches the expected file
+  // For each entry in the directory that matches the expected file
   // name pattern, determine if the file resources are stale and if
   // so, remove the file resources. Note, instrumented HotSpot processes
   // for this user may start and/or terminate during this search and
   // remove or create new files in this directory. The behavior of this
   // loop under these conditions is dependent upon the implementation of
   // opendir/readdir.
-  //
   struct dirent* entry;
   char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
   errno = 0;
   while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
 
@@ -528,56 +766,55 @@
 
       if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
 
-        // attempt to remove all unexpected files, except "." and ".."
-        remove_file(dirname, entry->d_name);
+        // Attempt to remove all unexpected files, except "." and "..".
+        unlink(entry->d_name);
       }
 
       errno = 0;
       continue;
     }
 
-    // we now have a file name that converts to a valid integer
+    // We now have a file name that converts to a valid integer
     // that could represent a process id . if this process id
     // matches the current process id or the process is not running,
     // then remove the stale file resources.
     //
-    // process liveness is detected by sending signal number 0 to
+    // Process liveness is detected by sending signal number 0 to
     // the process id (see kill(2)). if kill determines that the
     // process does not exist, then the file resources are removed.
     // if kill determines that that we don't have permission to
     // signal the process, then the file resources are assumed to
     // be stale and are removed because the resources for such a
     // process should be in a different user specific directory.
-    //
     if ((pid == os::current_process_id()) ||
         (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
 
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
     }
     errno = 0;
   }
-  os::closedir(dirp);
+
+  // Close the directory and reset the current working directory.
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
+
   FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
-// make the user specific temporary directory. Returns true if
+// Make the user specific temporary directory. Returns true if
 // the directory exists and is secure upon return. Returns false
 // if the directory exists but is either a symlink, is otherwise
 // insecure, or if an error occurred.
-//
 static bool make_user_tmp_dir(const char* dirname) {
 
-  // create the directory with 0755 permissions. note that the directory
+  // Create the directory with 0755 permissions. note that the directory
   // will be owned by euid::egid, which may not be the same as uid::gid.
-  //
   if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
     if (errno == EEXIST) {
       // The directory already exists and was probably created by another
       // JVM instance. However, this could also be the result of a
       // deliberate symlink. Verify that the existing directory is safe.
-      //
       if (!is_directory_secure(dirname)) {
-        // directory is not secure
+        // Directory is not secure.
         if (PrintMiscellaneous && Verbose) {
           warning("%s directory is insecure\n", dirname);
         }
@@ -613,19 +850,63 @@
     return -1;
   }
 
+  int saved_cwd_fd;
+  // Open the directory and set the current working directory to it.
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so cannot create shared
+    // memory file.
+    return -1;
+  }
+
+  // Open the filename in the current directory.
+  // Cannot use O_TRUNC here; truncation of an existing file has to happen
+  // after the is_file_secure() check below.
   int result;
 
-  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
+#else
+  // workaround function (jdk6 code)
+  RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
+#endif
+
   if (result == OS_ERR) {
     if (PrintMiscellaneous && Verbose) {
-      warning("could not create file %s: %s\n", filename, strerror(errno));
+      if (errno == ELOOP) {
+        warning("file %s is a symlink and is not secure\n", filename);
+      } else {
+        warning("could not create file %s: %s\n", filename, strerror(errno));
+      }
     }
+    // Close the directory and reset the current working directory.
+    close_directory_secure_cwd(dirp, saved_cwd_fd);
+
     return -1;
   }
+  // Close the directory and reset the current working directory.
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
 
   // save the file descriptor
   int fd = result;
 
+  // Check to see if the file is secure.
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  // Truncate the file to get rid of any existing data.
+  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not truncate shared memory file: %s\n", strerror(errno));
+    }
+    ::close(fd);
+    return -1;
+  }
   // set the file size
   RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   if (result == OS_ERR) {
@@ -647,7 +928,14 @@
 
   // open the file
   int result;
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case
+#ifdef O_NOFOLLOW
   RESTARTABLE(::open(filename, oflags), result);
+#else
+  RESTARTABLE(::open_o_nofollow(filename, oflags), result);
+#endif
+
   if (result == OS_ERR) {
     if (errno == ENOENT) {
       THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -661,8 +949,15 @@
       THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
     }
   }
+  int fd = result;
 
-  return result;
+  // Check to see if the file is secure.
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 // create a named shared memory region. returns the address of the
@@ -694,13 +989,21 @@
   char* dirname = get_user_tmp_dir(user_name);
   char* filename = get_sharedmem_filename(dirname, vmid);
 
+  // Get the short filename.
+  char* short_filename = strrchr(filename, '/');
+  if (short_filename == NULL) {
+    short_filename = filename;
+  } else {
+    short_filename++;
+  }
+
   // cleanup any stale shared memory files
   cleanup_sharedmem_resources(dirname);
 
   assert(((size > 0) && (size % os::vm_page_size() == 0)),
          "unexpected PerfMemory region size");
 
-  fd = create_sharedmem_resources(dirname, filename, size);
+  fd = create_sharedmem_resources(dirname, short_filename, size);
 
   FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
@@ -732,6 +1035,9 @@
   // clear the shared memory region
   (void)::memset((void*) mapAddress, 0, size);
 
+  // It does not go through os api, the operation has to record from here.
+  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
   return mapAddress;
 }
 
@@ -806,7 +1112,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -818,12 +1124,18 @@
   // constructs for the file and the shared memory mapping.
   if (mode == PerfMemory::PERF_MODE_RO) {
     mmap_prot = PROT_READ;
+
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open.
+#ifdef O_NOFOLLOW
+    file_flags = O_RDONLY | O_NOFOLLOW;
+#else
     file_flags = O_RDONLY;
+#endif
   }
   else if (mode == PerfMemory::PERF_MODE_RW) {
 #ifdef LATER
     mmap_prot = PROT_READ | PROT_WRITE;
-    file_flags = O_RDWR;
+    file_flags = O_RDWR | O_NOFOLLOW;
 #else
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Unsupported access mode");
@@ -853,6 +1165,9 @@
   //
   if (!is_directory_secure(dirname)) {
     FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+    if (luser != user) {
+      FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+    }
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Process not found");
   }
@@ -897,6 +1212,9 @@
               "Could not map PerfMemory");
   }
 
+  // It does not go through os api, the operation has to record from here.
+  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
   *addr = mapAddress;
   *sizep = size;
 
--- a/src/os/bsd/vm/os_bsd.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/bsd/vm/os_bsd.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -3745,9 +3745,6 @@
   return JNI_OK;
 }
 
-// this is called at the end of vm_initialization
-void os::init_3(void) { }
-
 // Mark the polling page as unreadable
 void os::make_polling_page_unreadable(void) {
   if( !guard_memory((char*)_polling_page, Bsd::page_size()) )
--- a/src/os/bsd/vm/perfMemory_bsd.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -197,7 +197,38 @@
 }
 
 
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+    // The path represents a link or some non-directory file type,
+    // which is not what we expected. Declare it insecure.
+    //
+    return false;
+  }
+  // We have an existing directory, check if the permissions are safe.
+  //
+  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+    // The directory is open for writing and could be subjected
+    // to a symlink or a hard link attack. Declare it insecure.
+    //
+    return false;
+  }
+  // See if the uid of the directory matches the effective uid of the process.
+  //
+  if (statp->st_uid != geteuid()) {
+    // The directory was not created by this user, declare it insecure.
+    //
+    return false;
+  }
+  return true;
+}
+
+
+// Check if the given path is considered a secure directory for
 // the backing store files. Returns true if the directory exists
 // and is considered a secure location. Returns false if the path
 // is a symbolic link or if an error occurred.
@@ -211,27 +242,185 @@
     return false;
   }
 
-  // the path exists, now check it's mode
-  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
-    // the path represents a link or some non-directory file type,
-    // which is not what we expected. declare it insecure.
-    //
+  // The path exists, see if it is secure.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // The path exists, now check its mode.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+  struct stat statbuf1;
+  struct stat statbuf2;
+  int result = 0;
+
+  RESTARTABLE(::fstat(fd1, &statbuf1), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+  RESTARTABLE(::fstat(fd2, &statbuf2), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  if ((statbuf1.st_ino == statbuf2.st_ino) &&
+      (statbuf1.st_dev == statbuf2.st_dev)) {
+    return true;
+  } else {
     return false;
   }
-  else {
-    // we have an existing directory, check if the permissions are safe.
-    //
-    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
-      // the directory is open for writing and could be subjected
-      // to a symlnk attack. declare it insecure.
-      //
-      return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+  // Open the directory using open() so that it can be verified
+  // to be secure by calling is_dirfd_secure(), opendir() and then check
+  // to see if they are the same file system object.  This method does not
+  // introduce a window of opportunity for the directory to be attacked that
+  // calling opendir() and is_directory_secure() does.
+  int result;
+  DIR *dirp = NULL;
+  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+  if (result == OS_ERR) {
+    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+    if (PrintMiscellaneous && Verbose) {
+      if (errno == ELOOP) {
+        warning("directory %s is a symlink and is not secure\n", dirname);
+      } else {
+        warning("could not open directory %s: %s\n", dirname, strerror(errno));
+      }
     }
+    return dirp;
+  }
+  int fd = result;
+
+  // Determine if the open directory is secure.
+  if (!is_dirfd_secure(fd)) {
+    // The directory is not a secure directory.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Open the directory.
+  dirp = ::opendir(dirname);
+  if (dirp == NULL) {
+    // The directory doesn't exist, close fd and return.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Check to make sure fd and dirp are referencing the same file system object.
+  if (!is_same_fsobject(fd, dirfd(dirp))) {
+    // The directory is not secure.
+    os::close(fd);
+    os::closedir(dirp);
+    dirp = NULL;
+    return dirp;
+  }
+
+  // Close initial open now that we know directory is secure
+  os::close(fd);
+
+  return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions.  Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+  // Open the directory.
+  DIR* dirp = open_directory_secure(dirname);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+    return dirp;
+  }
+  int fd = dirfd(dirp);
+
+  // Open a fd to the cwd and save it off.
+  int result;
+  RESTARTABLE(::open(".", O_RDONLY), result);
+  if (result == OS_ERR) {
+    *saved_cwd_fd = -1;
+  } else {
+    *saved_cwd_fd = result;
+  }
+
+  // Set the current directory to dirname by using the fd of the directory.
+  result = fchdir(fd);
+
+  return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+  int result;
+  // If we have a saved cwd change back to it and close the fd.
+  if (saved_cwd_fd != -1) {
+    result = fchdir(saved_cwd_fd);
+    ::close(saved_cwd_fd);
+  }
+
+  // Close the directory.
+  os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+  int result;
+  struct stat statbuf;
+
+  // Determine if the file is secure.
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed on %s: %s\n", filename, strerror(errno));
+    }
+    return false;
+  }
+  if (statbuf.st_nlink > 1) {
+    // A file with multiple links is not expected.
+    if (PrintMiscellaneous && Verbose) {
+      warning("file %s has multiple links\n", filename);
+    }
+    return false;
   }
   return true;
 }
 
-
 // return the user name for the given user id
 //
 // the caller is expected to free the allocated memory.
@@ -317,9 +506,11 @@
 
   const char* tmpdirname = os::get_temp_directory();
 
+  // open the temp directory
   DIR* tmpdirp = os::opendir(tmpdirname);
 
   if (tmpdirp == NULL) {
+    // Cannot open the directory to get the user name, return.
     return NULL;
   }
 
@@ -344,25 +535,14 @@
     strcat(usrdir_name, "/");
     strcat(usrdir_name, dentry->d_name);
 
-    DIR* subdirp = os::opendir(usrdir_name);
+    // open the user directory
+    DIR* subdirp = open_directory_secure(usrdir_name);
 
     if (subdirp == NULL) {
       FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
       continue;
     }
 
-    // Since we don't create the backing store files in directories
-    // pointed to by symbolic links, we also don't follow them when
-    // looking for the files. We check for a symbolic link after the
-    // call to opendir in order to eliminate a small window where the
-    // symlink can be exploited.
-    //
-    if (!is_directory_secure(usrdir_name)) {
-      FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
-      os::closedir(subdirp);
-      continue;
-    }
-
     struct dirent* udentry;
     char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
@@ -465,26 +645,6 @@
 }
 
 
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
-  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
-  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
-  strcpy(path, dirname);
-  strcat(path, "/");
-  strcat(path, filename);
-
-  remove_file(path);
-
-  FREE_C_HEAP_ARRAY(char, path, mtInternal);
-}
-
-
 // cleanup stale shared memory resources
 //
 // This method attempts to remove all stale shared memory files in
@@ -496,16 +656,11 @@
 //
 static void cleanup_sharedmem_resources(const char* dirname) {
 
-  // open the user temp directory
-  DIR* dirp = os::opendir(dirname);
-
+  int saved_cwd_fd;
+  // open the directory and set the current working directory to it
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   if (dirp == NULL) {
-    // directory doesn't exist, so there is nothing to cleanup
-    return;
-  }
-
-  if (!is_directory_secure(dirname)) {
-    // the directory is not a secure directory
+    // directory doesn't exist or is insecure, so there is nothing to cleanup
     return;
   }
 
@@ -519,6 +674,7 @@
   //
   struct dirent* entry;
   char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
   errno = 0;
   while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
 
@@ -529,7 +685,7 @@
       if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
 
         // attempt to remove all unexpected files, except "." and ".."
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
       }
 
       errno = 0;
@@ -552,11 +708,14 @@
     if ((pid == os::current_process_id()) ||
         (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
 
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
     }
     errno = 0;
   }
-  os::closedir(dirp);
+
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
+
   FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
@@ -613,19 +772,54 @@
     return -1;
   }
 
-  int result;
+  int saved_cwd_fd;
+  // open the directory and set the current working directory to it
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so cannot create shared
+    // memory file.
+    return -1;
+  }
 
-  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  // Open the filename in the current directory.
+  // Cannot use O_TRUNC here; truncation of an existing file has to happen
+  // after the is_file_secure() check below.
+  int result;
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   if (result == OS_ERR) {
     if (PrintMiscellaneous && Verbose) {
-      warning("could not create file %s: %s\n", filename, strerror(errno));
+      if (errno == ELOOP) {
+        warning("file %s is a symlink and is not secure\n", filename);
+      } else {
+        warning("could not create file %s: %s\n", filename, strerror(errno));
+      }
     }
+    // close the directory and reset the current working directory
+    close_directory_secure_cwd(dirp, saved_cwd_fd);
+
     return -1;
   }
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
 
   // save the file descriptor
   int fd = result;
 
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  // truncate the file to get rid of any existing data
+  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not truncate shared memory file: %s\n", strerror(errno));
+    }
+    ::close(fd);
+    return -1;
+  }
   // set the file size
   RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   if (result == OS_ERR) {
@@ -683,8 +877,15 @@
       THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
+  int fd = result;
 
-  return result;
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 // create a named shared memory region. returns the address of the
@@ -716,13 +917,21 @@
   char* dirname = get_user_tmp_dir(user_name);
   char* filename = get_sharedmem_filename(dirname, vmid);
 
+  // get the short filename
+  char* short_filename = strrchr(filename, '/');
+  if (short_filename == NULL) {
+    short_filename = filename;
+  } else {
+    short_filename++;
+  }
+
   // cleanup any stale shared memory files
   cleanup_sharedmem_resources(dirname);
 
   assert(((size > 0) && (size % os::vm_page_size() == 0)),
          "unexpected PerfMemory region size");
 
-  fd = create_sharedmem_resources(dirname, filename, size);
+  fd = create_sharedmem_resources(dirname, short_filename, size);
 
   FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
@@ -837,12 +1046,12 @@
   // constructs for the file and the shared memory mapping.
   if (mode == PerfMemory::PERF_MODE_RO) {
     mmap_prot = PROT_READ;
-    file_flags = O_RDONLY;
+    file_flags = O_RDONLY | O_NOFOLLOW;
   }
   else if (mode == PerfMemory::PERF_MODE_RW) {
 #ifdef LATER
     mmap_prot = PROT_READ | PROT_WRITE;
-    file_flags = O_RDWR;
+    file_flags = O_RDWR | O_NOFOLLOW;
 #else
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Unsupported access mode");
--- a/src/os/linux/vm/os_linux.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/linux/vm/os_linux.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -160,35 +160,6 @@
 // Declarations
 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
 
-#ifdef JAVASE_EMBEDDED
-class MemNotifyThread: public Thread {
-  friend class VMStructs;
- public:
-  virtual void run();
-
- private:
-  static MemNotifyThread* _memnotify_thread;
-  int _fd;
-
- public:
-
-  // Constructor
-  MemNotifyThread(int fd);
-
-  // Tester
-  bool is_memnotify_thread() const { return true; }
-
-  // Printing
-  char* name() const { return (char*)"Linux MemNotify Thread"; }
-
-  // Returns the single instance of the MemNotifyThread
-  static MemNotifyThread* memnotify_thread() { return _memnotify_thread; }
-
-  // Create and start the single instance of MemNotifyThread
-  static void start();
-};
-#endif // JAVASE_EMBEDDED
-
 // utility functions
 
 static int SR_initialize();
@@ -252,30 +223,7 @@
 #endif
 
 // Cpu architecture string
-#if   defined(ZERO)
-static char cpu_arch[] = ZERO_LIBARCH;
-#elif defined(IA64)
-static char cpu_arch[] = "ia64";
-#elif defined(IA32)
-static char cpu_arch[] = "i386";
-#elif defined(AMD64)
-static char cpu_arch[] = "amd64";
-#elif defined(ARM)
-static char cpu_arch[] = "arm";
-#elif defined(PPC32)
-static char cpu_arch[] = "ppc";
-#elif defined(PPC64)
-static char cpu_arch[] = "ppc64";
-#elif defined(SPARC)
-#  ifdef _LP64
-static char cpu_arch[] = "sparcv9";
-#  else
-static char cpu_arch[] = "sparc";
-#  endif
-#else
-#error Add appropriate cpu_arch setting
-#endif
-
+static char cpu_arch[] = HOTSPOT_LIB_ARCH;
 
 // pid_t gettid()
 //
@@ -4936,17 +4884,6 @@
   return JNI_OK;
 }
 
-// this is called at the end of vm_initialization
-void os::init_3(void) {
-#ifdef JAVASE_EMBEDDED
-  // Start the MemNotifyThread
-  if (LowMemoryProtection) {
-    MemNotifyThread::start();
-  }
-  return;
-#endif
-}
-
 // Mark the polling page as unreadable
 void os::make_polling_page_unreadable(void) {
   if( !guard_memory((char*)_polling_page, Linux::page_size()) )
@@ -6123,83 +6060,6 @@
   return strlen(buffer);
 }
 
-#ifdef JAVASE_EMBEDDED
-//
-// A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory.
-//
-MemNotifyThread* MemNotifyThread::_memnotify_thread = NULL;
-
-// ctor
-//
-MemNotifyThread::MemNotifyThread(int fd): Thread() {
-  assert(memnotify_thread() == NULL, "we can only allocate one MemNotifyThread");
-  _fd = fd;
-
-  if (os::create_thread(this, os::os_thread)) {
-    _memnotify_thread = this;
-    os::set_priority(this, NearMaxPriority);
-    os::start_thread(this);
-  }
-}
-
-// Where all the work gets done
-//
-void MemNotifyThread::run() {
-  assert(this == memnotify_thread(), "expected the singleton MemNotifyThread");
-
-  // Set up the select arguments
-  fd_set rfds;
-  if (_fd != -1) {
-    FD_ZERO(&rfds);
-    FD_SET(_fd, &rfds);
-  }
-
-  // Now wait for the mem_notify device to wake up
-  while (1) {
-    // Wait for the mem_notify device to signal us..
-    int rc = select(_fd+1, _fd != -1 ? &rfds : NULL, NULL, NULL, NULL);
-    if (rc == -1) {
-      perror("select!\n");
-      break;
-    } else if (rc) {
-      //ssize_t free_before = os::available_memory();
-      //tty->print ("Notified: Free: %dK \n",os::available_memory()/1024);
-
-      // The kernel is telling us there is not much memory left...
-      // try to do something about that
-
-      // If we are not already in a GC, try one.
-      if (!Universe::heap()->is_gc_active()) {
-        Universe::heap()->collect(GCCause::_allocation_failure);
-
-        //ssize_t free_after = os::available_memory();
-        //tty->print ("Post-Notify: Free: %dK\n",free_after/1024);
-        //tty->print ("GC freed: %dK\n", (free_after - free_before)/1024);
-      }
-      // We might want to do something like the following if we find the GC's are not helping...
-      // Universe::heap()->size_policy()->set_gc_time_limit_exceeded(true);
-    }
-  }
-}
-
-//
-// See if the /dev/mem_notify device exists, and if so, start a thread to monitor it.
-//
-void MemNotifyThread::start() {
-  int    fd;
-  fd = open ("/dev/mem_notify", O_RDONLY, 0);
-  if (fd < 0) {
-      return;
-  }
-
-  if (memnotify_thread() == NULL) {
-    new MemNotifyThread(fd);
-  }
-}
-
-#endif // JAVASE_EMBEDDED
-
-
 /////////////// Unit tests ///////////////
 
 #ifndef PRODUCT
--- a/src/os/linux/vm/perfMemory_linux.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/linux/vm/perfMemory_linux.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -197,7 +197,38 @@
 }
 
 
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+    // The path represents a link or some non-directory file type,
+    // which is not what we expected. Declare it insecure.
+    //
+    return false;
+  }
+  // We have an existing directory, check if the permissions are safe.
+  //
+  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+    // The directory is open for writing and could be subjected
+    // to a symlink or a hard link attack. Declare it insecure.
+    //
+    return false;
+  }
+  // See if the uid of the directory matches the effective uid of the process.
+  //
+  if (statp->st_uid != geteuid()) {
+    // The directory was not created by this user, declare it insecure.
+    //
+    return false;
+  }
+  return true;
+}
+
+
+// Check if the given path is considered a secure directory for
 // the backing store files. Returns true if the directory exists
 // and is considered a secure location. Returns false if the path
 // is a symbolic link or if an error occurred.
@@ -211,22 +242,180 @@
     return false;
   }
 
-  // the path exists, now check it's mode
-  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
-    // the path represents a link or some non-directory file type,
-    // which is not what we expected. declare it insecure.
-    //
+  // The path exists, see if it is secure.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // The path exists, now check its mode.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+  struct stat statbuf1;
+  struct stat statbuf2;
+  int result = 0;
+
+  RESTARTABLE(::fstat(fd1, &statbuf1), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+  RESTARTABLE(::fstat(fd2, &statbuf2), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  if ((statbuf1.st_ino == statbuf2.st_ino) &&
+      (statbuf1.st_dev == statbuf2.st_dev)) {
+    return true;
+  } else {
     return false;
   }
-  else {
-    // we have an existing directory, check if the permissions are safe.
-    //
-    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
-      // the directory is open for writing and could be subjected
-      // to a symlnk attack. declare it insecure.
-      //
-      return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+  // Open the directory using open() so that it can be verified
+  // to be secure by calling is_dirfd_secure(), opendir() and then check
+  // to see if they are the same file system object.  This method does not
+  // introduce a window of opportunity for the directory to be attacked that
+  // calling opendir() and is_directory_secure() does.
+  int result;
+  DIR *dirp = NULL;
+  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      if (errno == ELOOP) {
+        warning("directory %s is a symlink and is not secure\n", dirname);
+      } else {
+        warning("could not open directory %s: %s\n", dirname, strerror(errno));
+      }
     }
+    return dirp;
+  }
+  int fd = result;
+
+  // Determine if the open directory is secure.
+  if (!is_dirfd_secure(fd)) {
+    // The directory is not a secure directory.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Open the directory.
+  dirp = ::opendir(dirname);
+  if (dirp == NULL) {
+    // The directory doesn't exist, close fd and return.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Check to make sure fd and dirp are referencing the same file system object.
+  if (!is_same_fsobject(fd, dirfd(dirp))) {
+    // The directory is not secure.
+    os::close(fd);
+    os::closedir(dirp);
+    dirp = NULL;
+    return dirp;
+  }
+
+  // Close initial open now that we know directory is secure
+  os::close(fd);
+
+  return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions.  Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+  // Open the directory.
+  DIR* dirp = open_directory_secure(dirname);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+    return dirp;
+  }
+  int fd = dirfd(dirp);
+
+  // Open a fd to the cwd and save it off.
+  int result;
+  RESTARTABLE(::open(".", O_RDONLY), result);
+  if (result == OS_ERR) {
+    *saved_cwd_fd = -1;
+  } else {
+    *saved_cwd_fd = result;
+  }
+
+  // Set the current directory to dirname by using the fd of the directory.
+  result = fchdir(fd);
+
+  return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+  int result;
+  // If we have a saved cwd change back to it and close the fd.
+  if (saved_cwd_fd != -1) {
+    result = fchdir(saved_cwd_fd);
+    ::close(saved_cwd_fd);
+  }
+
+  // Close the directory.
+  os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+  int result;
+  struct stat statbuf;
+
+  // Determine if the file is secure.
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed on %s: %s\n", filename, strerror(errno));
+    }
+    return false;
+  }
+  if (statbuf.st_nlink > 1) {
+    // A file with multiple links is not expected.
+    if (PrintMiscellaneous && Verbose) {
+      warning("file %s has multiple links\n", filename);
+    }
+    return false;
   }
   return true;
 }
@@ -317,9 +506,11 @@
 
   const char* tmpdirname = os::get_temp_directory();
 
+  // open the temp directory
   DIR* tmpdirp = os::opendir(tmpdirname);
 
   if (tmpdirp == NULL) {
+    // Cannot open the directory to get the user name, return.
     return NULL;
   }
 
@@ -344,7 +535,8 @@
     strcat(usrdir_name, "/");
     strcat(usrdir_name, dentry->d_name);
 
-    DIR* subdirp = os::opendir(usrdir_name);
+    // open the user directory
+    DIR* subdirp = open_directory_secure(usrdir_name);
 
     if (subdirp == NULL) {
       FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
@@ -465,26 +657,6 @@
 }
 
 
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
-  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
-  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
-  strcpy(path, dirname);
-  strcat(path, "/");
-  strcat(path, filename);
-
-  remove_file(path);
-
-  FREE_C_HEAP_ARRAY(char, path, mtInternal);
-}
-
-
 // cleanup stale shared memory resources
 //
 // This method attempts to remove all stale shared memory files in
@@ -496,16 +668,11 @@
 //
 static void cleanup_sharedmem_resources(const char* dirname) {
 
-  // open the user temp directory
-  DIR* dirp = os::opendir(dirname);
-
+  int saved_cwd_fd;
+  // open the directory
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   if (dirp == NULL) {
-    // directory doesn't exist, so there is nothing to cleanup
-    return;
-  }
-
-  if (!is_directory_secure(dirname)) {
-    // the directory is not a secure directory
+    // directory doesn't exist or is insecure, so there is nothing to cleanup
     return;
   }
 
@@ -519,6 +686,7 @@
   //
   struct dirent* entry;
   char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
   errno = 0;
   while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
 
@@ -527,9 +695,8 @@
     if (pid == 0) {
 
       if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
-
         // attempt to remove all unexpected files, except "." and ".."
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
       }
 
       errno = 0;
@@ -551,12 +718,14 @@
     //
     if ((pid == os::current_process_id()) ||
         (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
-
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
     }
     errno = 0;
   }
-  os::closedir(dirp);
+
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
+
   FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
@@ -613,19 +782,54 @@
     return -1;
   }
 
-  int result;
+  int saved_cwd_fd;
+  // open the directory and set the current working directory to it
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so cannot create shared
+    // memory file.
+    return -1;
+  }
 
-  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  // Open the filename in the current directory.
+  // Cannot use O_TRUNC here; truncation of an existing file has to happen
+  // after the is_file_secure() check below.
+  int result;
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   if (result == OS_ERR) {
     if (PrintMiscellaneous && Verbose) {
-      warning("could not create file %s: %s\n", filename, strerror(errno));
+      if (errno == ELOOP) {
+        warning("file %s is a symlink and is not secure\n", filename);
+      } else {
+        warning("could not create file %s: %s\n", filename, strerror(errno));
+      }
     }
+    // close the directory and reset the current working directory
+    close_directory_secure_cwd(dirp, saved_cwd_fd);
+
     return -1;
   }
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
 
   // save the file descriptor
   int fd = result;
 
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  // truncate the file to get rid of any existing data
+  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not truncate shared memory file: %s\n", strerror(errno));
+    }
+    ::close(fd);
+    return -1;
+  }
   // set the file size
   RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   if (result == OS_ERR) {
@@ -683,8 +887,15 @@
       THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
+  int fd = result;
 
-  return result;
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 // create a named shared memory region. returns the address of the
@@ -715,6 +926,13 @@
 
   char* dirname = get_user_tmp_dir(user_name);
   char* filename = get_sharedmem_filename(dirname, vmid);
+  // get the short filename
+  char* short_filename = strrchr(filename, '/');
+  if (short_filename == NULL) {
+    short_filename = filename;
+  } else {
+    short_filename++;
+  }
 
   // cleanup any stale shared memory files
   cleanup_sharedmem_resources(dirname);
@@ -722,7 +940,7 @@
   assert(((size > 0) && (size % os::vm_page_size() == 0)),
          "unexpected PerfMemory region size");
 
-  fd = create_sharedmem_resources(dirname, filename, size);
+  fd = create_sharedmem_resources(dirname, short_filename, size);
 
   FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
@@ -837,12 +1055,12 @@
   // constructs for the file and the shared memory mapping.
   if (mode == PerfMemory::PERF_MODE_RO) {
     mmap_prot = PROT_READ;
-    file_flags = O_RDONLY;
+    file_flags = O_RDONLY | O_NOFOLLOW;
   }
   else if (mode == PerfMemory::PERF_MODE_RW) {
 #ifdef LATER
     mmap_prot = PROT_READ | PROT_WRITE;
-    file_flags = O_RDWR;
+    file_flags = O_RDWR | O_NOFOLLOW;
 #else
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Unsupported access mode");
--- a/src/os/solaris/vm/jvm_solaris.h	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/solaris/vm/jvm_solaris.h	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,9 @@
  * JNI conversion, which should be sorted out later.
  */
 
+#define __USE_LEGACY_PROTOTYPES__
 #include <dirent.h>             /* For DIR */
+#undef __USE_LEGACY_PROTOTYPES__
 #include <sys/param.h>          /* For MAXPATHLEN */
 #include <sys/socket.h>         /* For socklen_t */
 #include <unistd.h>             /* For F_OK, R_OK, W_OK */
--- a/src/os/solaris/vm/os_solaris.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/solaris/vm/os_solaris.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -5194,10 +5194,6 @@
   return JNI_OK;
 }
 
-void os::init_3(void) {
-  return;
-}
-
 // Mark the polling page as unreadable
 void os::make_polling_page_unreadable(void) {
   if( mprotect((char *)_polling_page, page_size, PROT_NONE) != 0 )
--- a/src/os/solaris/vm/perfMemory_solaris.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/solaris/vm/perfMemory_solaris.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -199,7 +199,38 @@
 }
 
 
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+    // The path represents a link or some non-directory file type,
+    // which is not what we expected. Declare it insecure.
+    //
+    return false;
+  }
+  // We have an existing directory, check if the permissions are safe.
+  //
+  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+    // The directory is open for writing and could be subjected
+    // to a symlink or a hard link attack. Declare it insecure.
+    //
+    return false;
+  }
+  // See if the uid of the directory matches the effective uid of the process.
+  //
+  if (statp->st_uid != geteuid()) {
+    // The directory was not created by this user, declare it insecure.
+    //
+    return false;
+  }
+  return true;
+}
+
+
+// Check if the given path is considered a secure directory for
 // the backing store files. Returns true if the directory exists
 // and is considered a secure location. Returns false if the path
 // is a symbolic link or if an error occurred.
@@ -213,27 +244,185 @@
     return false;
   }
 
-  // the path exists, now check it's mode
-  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
-    // the path represents a link or some non-directory file type,
-    // which is not what we expected. declare it insecure.
-    //
+  // The path exists, see if it is secure.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // The path exists, now check its mode.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+  struct stat statbuf1;
+  struct stat statbuf2;
+  int result = 0;
+
+  RESTARTABLE(::fstat(fd1, &statbuf1), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+  RESTARTABLE(::fstat(fd2, &statbuf2), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  if ((statbuf1.st_ino == statbuf2.st_ino) &&
+      (statbuf1.st_dev == statbuf2.st_dev)) {
+    return true;
+  } else {
     return false;
   }
-  else {
-    // we have an existing directory, check if the permissions are safe.
-    //
-    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
-      // the directory is open for writing and could be subjected
-      // to a symlnk attack. declare it insecure.
-      //
-      return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+  // Open the directory using open() so that it can be verified
+  // to be secure by calling is_dirfd_secure(), opendir() and then check
+  // to see if they are the same file system object.  This method does not
+  // introduce a window of opportunity for the directory to be attacked that
+  // calling opendir() and is_directory_secure() does.
+  int result;
+  DIR *dirp = NULL;
+  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+  if (result == OS_ERR) {
+    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+    if (PrintMiscellaneous && Verbose) {
+      if (errno == ELOOP) {
+        warning("directory %s is a symlink and is not secure\n", dirname);
+      } else {
+        warning("could not open directory %s: %s\n", dirname, strerror(errno));
+      }
     }
+    return dirp;
+  }
+  int fd = result;
+
+  // Determine if the open directory is secure.
+  if (!is_dirfd_secure(fd)) {
+    // The directory is not a secure directory.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Open the directory.
+  dirp = ::opendir(dirname);
+  if (dirp == NULL) {
+    // The directory doesn't exist, close fd and return.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Check to make sure fd and dirp are referencing the same file system object.
+  if (!is_same_fsobject(fd, dirp->dd_fd)) {
+    // The directory is not secure.
+    os::close(fd);
+    os::closedir(dirp);
+    dirp = NULL;
+    return dirp;
+  }
+
+  // Close initial open now that we know directory is secure
+  os::close(fd);
+
+  return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions.  Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+  // Open the directory.
+  DIR* dirp = open_directory_secure(dirname);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+    return dirp;
+  }
+  int fd = dirp->dd_fd;
+
+  // Open a fd to the cwd and save it off.
+  int result;
+  RESTARTABLE(::open(".", O_RDONLY), result);
+  if (result == OS_ERR) {
+    *saved_cwd_fd = -1;
+  } else {
+    *saved_cwd_fd = result;
+  }
+
+  // Set the current directory to dirname by using the fd of the directory.
+  result = fchdir(fd);
+
+  return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+  int result;
+  // If we have a saved cwd change back to it and close the fd.
+  if (saved_cwd_fd != -1) {
+    result = fchdir(saved_cwd_fd);
+    ::close(saved_cwd_fd);
+  }
+
+  // Close the directory.
+  os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+  int result;
+  struct stat statbuf;
+
+  // Determine if the file is secure.
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed on %s: %s\n", filename, strerror(errno));
+    }
+    return false;
+  }
+  if (statbuf.st_nlink > 1) {
+    // A file with multiple links is not expected.
+    if (PrintMiscellaneous && Verbose) {
+      warning("file %s has multiple links\n", filename);
+    }
+    return false;
   }
   return true;
 }
 
-
 // return the user name for the given user id
 //
 // the caller is expected to free the allocated memory.
@@ -308,9 +497,11 @@
 
   const char* tmpdirname = os::get_temp_directory();
 
+  // open the temp directory
   DIR* tmpdirp = os::opendir(tmpdirname);
 
   if (tmpdirp == NULL) {
+    // Cannot open the directory to get the user name, return.
     return NULL;
   }
 
@@ -335,7 +526,8 @@
     strcat(usrdir_name, "/");
     strcat(usrdir_name, dentry->d_name);
 
-    DIR* subdirp = os::opendir(usrdir_name);
+    // open the user directory
+    DIR* subdirp = open_directory_secure(usrdir_name);
 
     if (subdirp == NULL) {
       FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
@@ -504,26 +696,6 @@
 }
 
 
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
-  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
-  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
-  strcpy(path, dirname);
-  strcat(path, "/");
-  strcat(path, filename);
-
-  remove_file(path);
-
-  FREE_C_HEAP_ARRAY(char, path, mtInternal);
-}
-
-
 // cleanup stale shared memory resources
 //
 // This method attempts to remove all stale shared memory files in
@@ -535,16 +707,11 @@
 //
 static void cleanup_sharedmem_resources(const char* dirname) {
 
-  // open the user temp directory
-  DIR* dirp = os::opendir(dirname);
-
+  int saved_cwd_fd;
+  // open the directory
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   if (dirp == NULL) {
-    // directory doesn't exist, so there is nothing to cleanup
-    return;
-  }
-
-  if (!is_directory_secure(dirname)) {
-    // the directory is not a secure directory
+     // directory doesn't exist or is insecure, so there is nothing to cleanup
     return;
   }
 
@@ -558,6 +725,7 @@
   //
   struct dirent* entry;
   char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
   errno = 0;
   while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
 
@@ -568,7 +736,7 @@
       if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
 
         // attempt to remove all unexpected files, except "." and ".."
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
       }
 
       errno = 0;
@@ -591,11 +759,14 @@
     if ((pid == os::current_process_id()) ||
         (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
 
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
     }
     errno = 0;
   }
-  os::closedir(dirp);
+
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
+
   FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
@@ -652,19 +823,54 @@
     return -1;
   }
 
-  int result;
+  int saved_cwd_fd;
+  // open the directory and set the current working directory to it
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so cannot create shared
+    // memory file.
+    return -1;
+  }
 
-  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  // Open the filename in the current directory.
+  // Cannot use O_TRUNC here; truncation of an existing file has to happen
+  // after the is_file_secure() check below.
+  int result;
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   if (result == OS_ERR) {
     if (PrintMiscellaneous && Verbose) {
-      warning("could not create file %s: %s\n", filename, strerror(errno));
+      if (errno == ELOOP) {
+        warning("file %s is a symlink and is not secure\n", filename);
+      } else {
+        warning("could not create file %s: %s\n", filename, strerror(errno));
+      }
     }
+    // close the directory and reset the current working directory
+    close_directory_secure_cwd(dirp, saved_cwd_fd);
+
     return -1;
   }
+  // close the directory and reset the current working directory
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
 
   // save the file descriptor
   int fd = result;
 
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  // truncate the file to get rid of any existing data
+  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not truncate shared memory file: %s\n", strerror(errno));
+    }
+    ::close(fd);
+    return -1;
+  }
   // set the file size
   RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   if (result == OS_ERR) {
@@ -700,8 +906,15 @@
       THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
+  int fd = result;
 
-  return result;
+  // check to see if the file is secure
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 // create a named shared memory region. returns the address of the
@@ -733,13 +946,21 @@
   char* dirname = get_user_tmp_dir(user_name);
   char* filename = get_sharedmem_filename(dirname, vmid);
 
+  // get the short filename
+  char* short_filename = strrchr(filename, '/');
+  if (short_filename == NULL) {
+    short_filename = filename;
+  } else {
+    short_filename++;
+  }
+
   // cleanup any stale shared memory files
   cleanup_sharedmem_resources(dirname);
 
   assert(((size > 0) && (size % os::vm_page_size() == 0)),
          "unexpected PerfMemory region size");
 
-  fd = create_sharedmem_resources(dirname, filename, size);
+  fd = create_sharedmem_resources(dirname, short_filename, size);
 
   FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
@@ -855,12 +1076,12 @@
   // constructs for the file and the shared memory mapping.
   if (mode == PerfMemory::PERF_MODE_RO) {
     mmap_prot = PROT_READ;
-    file_flags = O_RDONLY;
+    file_flags = O_RDONLY | O_NOFOLLOW;
   }
   else if (mode == PerfMemory::PERF_MODE_RW) {
 #ifdef LATER
     mmap_prot = PROT_READ | PROT_WRITE;
-    file_flags = O_RDWR;
+    file_flags = O_RDWR | O_NOFOLLOW;
 #else
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Unsupported access mode");
--- a/src/os/windows/vm/os_windows.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os/windows/vm/os_windows.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -4062,10 +4062,6 @@
   return JNI_OK;
 }
 
-void os::init_3(void) {
-  return;
-}
-
 // Mark the polling page as unreadable
 void os::make_polling_page_unreadable(void) {
   DWORD old_status;
--- a/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -238,7 +238,13 @@
   // operation.  Note that some platforms only support this with the
   // limitation that the only valid value to store is the immediate
   // constant 1.  There is a test for this in JNI_CreateJavaVM().
-  return __sync_lock_test_and_set (dest, exchange_value);
+  jint result = __sync_lock_test_and_set (dest, exchange_value);
+  // All atomic operations are expected to be full memory barriers
+  // (see atomic.hpp). However, __sync_lock_test_and_set is not
+  // a full memory barrier, but an acquire barrier. Hence, this added
+  // barrier.
+  __sync_synchronize();
+  return result;
 #endif // M68K
 #endif // ARM
 }
@@ -251,7 +257,9 @@
 #ifdef M68K
   return m68k_lock_test_and_set(dest, exchange_value);
 #else
-  return __sync_lock_test_and_set (dest, exchange_value);
+  intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+  __sync_synchronize();
+  return result;
 #endif // M68K
 #endif // ARM
 }
--- a/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -26,8 +26,8 @@
 #include "runtime/os.hpp"
 #include "vm_version_sparc.hpp"
 
-static bool detect_niagara() {
-  char cpu[128];
+static bool cpuinfo_field_contains(const char* field, const char* value) {
+  char line[1024];
   bool rv = false;
 
   FILE* fp = fopen("/proc/cpuinfo", "r");
@@ -35,9 +35,10 @@
     return rv;
   }
 
-  while (!feof(fp)) {
-    if (fscanf(fp, "cpu\t\t: %100[^\n]", &cpu) == 1) {
-      if (strstr(cpu, "Niagara") != NULL) {
+  while (fgets(line, sizeof(line), fp) != NULL) {
+    assert(strlen(line) < sizeof(line) - 1, "buffer line[1024] is too small.");
+    if (strncmp(line, field, strlen(field)) == 0) {
+      if (strstr(line, value) != NULL) {
         rv = true;
       }
       break;
@@ -45,8 +46,15 @@
   }
 
   fclose(fp);
+  return rv;
+}
 
-  return rv;
+static bool detect_niagara() {
+  return cpuinfo_field_contains("cpu", "Niagara");
+}
+
+static bool detect_blkinit() {
+  return cpuinfo_field_contains("cpucaps", "blkinit");
 }
 
 int VM_Version::platform_features(int features) {
@@ -58,5 +66,9 @@
     features = niagara1_m | T_family_m;
   }
 
+  if (detect_blkinit()) {
+    features |= blk_init_instructions_m;
+  }
+
   return features;
 }
--- a/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -242,7 +242,13 @@
   // operation.  Note that some platforms only support this with the
   // limitation that the only valid value to store is the immediate
   // constant 1.  There is a test for this in JNI_CreateJavaVM().
-  return __sync_lock_test_and_set (dest, exchange_value);
+  jint result = __sync_lock_test_and_set (dest, exchange_value);
+  // All atomic operations are expected to be full memory barriers
+  // (see atomic.hpp). However, __sync_lock_test_and_set is not
+  // a full memory barrier, but an acquire barrier. Hence, this added
+  // barrier.
+  __sync_synchronize();
+  return result;
 #endif // M68K
 #endif // ARM
 }
@@ -255,7 +261,9 @@
 #ifdef M68K
   return m68k_lock_test_and_set(dest, exchange_value);
 #else
-  return __sync_lock_test_and_set (dest, exchange_value);
+  intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+  __sync_synchronize();
+  return result;
 #endif // M68K
 #endif // ARM
 }
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -264,7 +264,7 @@
                 CAST_FROM_FN_PTR(address, os::current_frame));
   if (os::is_first_C_frame(&myframe)) {
     // stack is not walkable
-    return frame(NULL, NULL, NULL);
+    return frame(NULL, NULL, false);
   } else {
     return os::get_sender_for_C_frame(&myframe);
   }
--- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -34,8 +34,7 @@
 #include <dlfcn.h>
 #include <link.h>
 
-extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
-extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result);
 
 // Functions from the library we need (signatures should match those in picl.h)
 extern "C" {
@@ -128,60 +127,87 @@
     bool is_inconsistent()  { return _state == INCONSISTENT; }
     void set_inconsistent() { _state = INCONSISTENT;         }
 
-    static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
-      UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
-      PICL* picl = state->_picl;
-      assert(!state->is_inconsistent(), "Precondition");
+    bool visit(picl_nodehdl_t nodeh, const char* name) {
+      assert(!is_inconsistent(), "Precondition");
       int curr;
-      if (picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
-        if (!state->is_assigned()) { // first iteration
-          state->set_value(curr);
-        } else if (curr != state->value()) { // following iterations
-          state->set_inconsistent();
+      if (_picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
+        if (!is_assigned()) { // first iteration
+          set_value(curr);
+        } else if (curr != value()) { // following iterations
+          set_inconsistent();
+        }
+        return true;
+      }
+      return false;
+    }
+  };
+
+  class CPUVisitor {
+    UniqueValueVisitor _l1_visitor;
+    UniqueValueVisitor _l2_visitor;
+    int _limit; // number of times visit() can be run
+  public:
+    CPUVisitor(PICL *picl, int limit) : _l1_visitor(picl), _l2_visitor(picl), _limit(limit) {}
+    static int visit(picl_nodehdl_t nodeh, void *arg) {
+      CPUVisitor *cpu_visitor = static_cast<CPUVisitor*>(arg);
+      UniqueValueVisitor* l1_visitor = cpu_visitor->l1_visitor();
+      UniqueValueVisitor* l2_visitor = cpu_visitor->l2_visitor();
+      if (!l1_visitor->is_inconsistent()) {
+        l1_visitor->visit(nodeh, "l1-dcache-line-size");
+      }
+      static const char* l2_data_cache_line_property_name = NULL;
+      // On the first visit determine the name of the l2 cache line size property and memoize it.
+      if (l2_data_cache_line_property_name == NULL) {
+        assert(!l2_visitor->is_inconsistent(), "First iteration cannot be inconsistent");
+        l2_data_cache_line_property_name = "l2-cache-line-size";
+        if (!l2_visitor->visit(nodeh, l2_data_cache_line_property_name)) {
+          l2_data_cache_line_property_name = "l2-dcache-line-size";
+          l2_visitor->visit(nodeh, l2_data_cache_line_property_name);
+        }
+      } else {
+        if (!l2_visitor->is_inconsistent()) {
+          l2_visitor->visit(nodeh, l2_data_cache_line_property_name);
         }
       }
-      if (state->is_inconsistent()) {
+
+      if (l1_visitor->is_inconsistent() && l2_visitor->is_inconsistent()) {
+        return PICL_WALK_TERMINATE;
+      }
+      cpu_visitor->_limit--;
+      if (cpu_visitor->_limit <= 0) {
         return PICL_WALK_TERMINATE;
       }
       return PICL_WALK_CONTINUE;
     }
+    UniqueValueVisitor* l1_visitor() { return &_l1_visitor; }
+    UniqueValueVisitor* l2_visitor() { return &_l2_visitor; }
   };
-
   int _L1_data_cache_line_size;
-  int _L2_cache_line_size;
+  int _L2_data_cache_line_size;
 public:
-  static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
-    return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
-  }
-  static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
-    return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
+  static int visit_cpu(picl_nodehdl_t nodeh, void *state) {
+    return CPUVisitor::visit(nodeh, state);
   }
 
-  PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) {
+  PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) {
     if (!open_library()) {
       return;
     }
     if (_picl_initialize() == PICL_SUCCESS) {
       picl_nodehdl_t rooth;
       if (_picl_get_root(&rooth) == PICL_SUCCESS) {
-        UniqueValueVisitor L1_state(this);
-        // Visit all "cpu" class instances
-        _picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
-        if (L1_state.is_initial()) { // Still initial, iteration found no values
-          // Try walk all "core" class instances, it might be a Fujitsu machine
-          _picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+        const char* cpu_class = "cpu";
+        // If it's a Fujitsu machine, it's a "core"
+        if (is_fujitsu) {
+          cpu_class = "core";
         }
-        if (L1_state.is_assigned()) { // Is there a value?
-          _L1_data_cache_line_size = L1_state.value();
+        CPUVisitor cpu_visitor(this, os::processor_count());
+        _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper);
+        if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value?
+          _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value();
         }
-
-        UniqueValueVisitor L2_state(this);
-        _picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
-        if (L2_state.is_initial()) {
-          _picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
-        }
-        if (L2_state.is_assigned()) {
-          _L2_cache_line_size = L2_state.value();
+        if (cpu_visitor.l2_visitor()->is_assigned()) {
+          _L2_data_cache_line_size = cpu_visitor.l2_visitor()->value();
         }
       }
       _picl_shutdown();
@@ -190,14 +216,12 @@
   }
 
   unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
-  unsigned int L2_cache_line_size() const      { return _L2_cache_line_size;      }
+  unsigned int L2_data_cache_line_size() const { return _L2_data_cache_line_size; }
 };
 
-extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
-  return PICL::get_l1_data_cache_line_size(nodeh, result);
-}
-extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
-  return PICL::get_l2_cache_line_size(nodeh, result);
+
+extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result) {
+  return PICL::visit_cpu(nodeh, result);
 }
 
 template<typename FuncType>
@@ -470,8 +494,8 @@
   }
 
   // Figure out cache line sizes using PICL
-  PICL picl;
-  _L2_cache_line_size      = picl.L2_cache_line_size();
+  PICL picl((features & sparc64_family_m) != 0);
+  _L2_data_cache_line_size = picl.L2_data_cache_line_size();
 
   return features;
 }
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +24,12 @@
 
 /**
  * A SAX based parser of LogCompilation output from HotSpot.  It takes a complete
- * @author never
  */
 
 package com.sun.hotspot.tools.compiler;
 
 import java.io.FileReader;
+import java.io.PrintStream;
 import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -133,6 +133,44 @@
         }
     };
 
+    class Jvms {
+        Jvms(Method method, int bci) {
+            this.method = method;
+            this.bci = bci;
+        }
+        final public Method method;
+        final public int bci;
+        final public String toString() {
+            return "@" + bci + " " + method;
+        }
+    }
+
+    class LockElimination extends BasicLogEvent {
+
+        ArrayList<Jvms> jvms = new ArrayList<Jvms>(1);
+        final String kind;
+        final String classId;
+        final String tagName;
+        LockElimination(String tagName, double start, String id, String kind, String classId) {
+            super(start, id);
+            this.kind = kind;
+            this.classId = classId;
+            this.tagName = tagName;
+        }
+
+        @Override
+        public void print(PrintStream stream) {
+            stream.printf("%s %s %s %s  %.3f ", getId(), tagName, kind, classId, getStart());
+            stream.print(jvms.toString());
+            stream.print("\n");
+        }
+
+        void addJVMS(Method method, int bci) {
+            jvms.add(new Jvms(method, bci));
+        }
+
+    }
+
     private ArrayList<LogEvent> events = new ArrayList<LogEvent>();
 
     private HashMap<String, String> types = new HashMap<String, String>();
@@ -145,6 +183,7 @@
     private Compilation compile;
     private CallSite site;
     private Stack<Phase> phaseStack = new Stack<Phase>();
+    private LockElimination currentLockElimination;
     private UncommonTrapEvent currentTrap;
     private Stack<CallSite> late_inline_scope;
 
@@ -188,7 +227,12 @@
         }
 
         LogParser log = new LogParser();
-        p.parse(new InputSource(reader), log);
+        try {
+            p.parse(new InputSource(reader), log);
+        } catch (Throwable th) {
+            th.printStackTrace();
+            // Carry on with what we've got...
+        }
 
         // Associate compilations with their NMethods
         for (NMethod nm : log.nmethods.values()) {
@@ -370,6 +414,15 @@
                 // uncommon trap inserted during parsing.
                 // ignore for now
             }
+        } else if (qname.startsWith("eliminate_lock")) {
+            String id = atts.getValue("compile_id");
+            if (id != null) {
+                id = makeId(atts);
+                String kind = atts.getValue("kind");
+                String classId = atts.getValue("class_id");
+                currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId);
+                events.add(currentLockElimination);
+            }
         } else if (qname.equals("late_inline")) {
             late_inline_scope = new Stack<CallSite>();
             site = new CallSite(-999, method(search(atts, "method")));
@@ -378,13 +431,14 @@
             // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
             if (currentTrap != null) {
                 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
+            } else if (currentLockElimination != null) {
+                  currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
             } else if (late_inline_scope != null) {
                 bci = Integer.parseInt(search(atts, "bci"));
                 site = new CallSite(bci, method(search(atts, "method")));
                 late_inline_scope.push(site);
             } else {
                 // Ignore <eliminate_allocation type='667'>,
-                //        <eliminate_lock lock='1'>,
                 //        <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
             }
         } else if (qname.equals("nmethod")) {
@@ -437,6 +491,8 @@
             scopes.pop();
         } else if (qname.equals("uncommon_trap")) {
             currentTrap = null;
+        } else if (qname.startsWith("eliminate_lock")) {
+            currentLockElimination = null;
         } else if (qname.equals("late_inline")) {
             // Populate late inlining info.
 
@@ -445,8 +501,8 @@
             CallSite caller = late_inline_scope.pop();
             Method m = compile.getMethod();
             if (m != caller.getMethod()) {
-                System.out.println(m);
-                System.out.println(caller.getMethod() + " bci: " + bci);
+                System.err.println(m);
+                System.err.println(caller.getMethod() + " bci: " + bci);
                 throw new InternalError("call site and late_inline info don't match");
             }
 
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 @@
     }
 
     public void print(PrintStream stream) {
-        stream.printf("%s uncommon trap %s %s\n", getId(), getReason(), getAction());
+        stream.printf("%s uncommon trap %.3f %s %s\n", getId(), getStart(), getReason(), getAction());
         stream.print(getJvms());
     }
 
--- a/src/share/vm/c1/c1_LIR.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_LIR.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -142,16 +142,11 @@
 
 
 #ifndef PRODUCT
-void LIR_Address::verify() const {
+void LIR_Address::verify0() const {
 #if defined(SPARC) || defined(PPC)
   assert(scale() == times_1, "Scaled addressing mode not available on SPARC/PPC and should not be used");
   assert(disp() == 0 || index()->is_illegal(), "can't have both");
 #endif
-#ifdef ARM
-  assert(disp() == 0 || index()->is_illegal(), "can't have both");
-  // Note: offsets higher than 4096 must not be rejected here. They can
-  // be handled by the back-end or will be rejected if not.
-#endif
 #ifdef _LP64
   assert(base()->is_cpu_register(), "wrong base operand");
   assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
--- a/src/share/vm/c1/c1_LIR.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_LIR.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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_C1_C1_LIR_HPP
 #define SHARE_VM_C1_C1_LIR_HPP
 
+#include "c1/c1_Defs.hpp"
 #include "c1/c1_ValueType.hpp"
 #include "oops/method.hpp"
 
@@ -561,7 +562,13 @@
   virtual BasicType type() const                 { return _type; }
   virtual void print_value_on(outputStream* out) const PRODUCT_RETURN;
 
-  void verify() const PRODUCT_RETURN;
+  void verify0() const PRODUCT_RETURN;
+#if defined(LIR_ADDRESS_PD_VERIFY) && !defined(PRODUCT)
+  void pd_verify() const;
+  void verify() const { pd_verify(); }
+#else
+  void verify() const { verify0(); }
+#endif
 
   static Scale scale(BasicType type);
 };
@@ -610,19 +617,15 @@
                                                                              LIR_OprDesc::float_type           |
                                                                              LIR_OprDesc::fpu_register         |
                                                                              LIR_OprDesc::single_size); }
-#if defined(ARM)
-  static LIR_Opr double_fpu(int reg1, int reg2)    { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::fpu_register | LIR_OprDesc::double_size); }
-  static LIR_Opr single_softfp(int reg)            { return (LIR_Opr)((reg  << LIR_OprDesc::reg1_shift) |                                     LIR_OprDesc::float_type  | LIR_OprDesc::cpu_register | LIR_OprDesc::single_size); }
-  static LIR_Opr double_softfp(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::cpu_register | LIR_OprDesc::double_size); }
-#endif
-#ifdef SPARC
+#if defined(C1_LIR_MD_HPP)
+# include C1_LIR_MD_HPP
+#elif defined(SPARC)
   static LIR_Opr double_fpu(int reg1, int reg2) { return (LIR_Opr)(intptr_t)((reg1 << LIR_OprDesc::reg1_shift) |
                                                                              (reg2 << LIR_OprDesc::reg2_shift) |
                                                                              LIR_OprDesc::double_type          |
                                                                              LIR_OprDesc::fpu_register         |
                                                                              LIR_OprDesc::double_size); }
-#endif
-#ifdef X86
+#elif defined(X86)
   static LIR_Opr double_fpu(int reg)            { return (LIR_Opr)(intptr_t)((reg  << LIR_OprDesc::reg1_shift) |
                                                                              (reg  << LIR_OprDesc::reg2_shift) |
                                                                              LIR_OprDesc::double_type          |
@@ -640,8 +643,7 @@
                                                                              LIR_OprDesc::fpu_register         |
                                                                              LIR_OprDesc::double_size          |
                                                                              LIR_OprDesc::is_xmm_mask); }
-#endif // X86
-#ifdef PPC
+#elif defined(PPC)
   static LIR_Opr double_fpu(int reg)            { return (LIR_Opr)(intptr_t)((reg  << LIR_OprDesc::reg1_shift) |
                                                                              (reg  << LIR_OprDesc::reg2_shift) |
                                                                              LIR_OprDesc::double_type          |
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "c1/c1_Defs.hpp"
 #include "c1/c1_Compilation.hpp"
 #include "c1/c1_FrameMap.hpp"
 #include "c1/c1_Instruction.hpp"
@@ -46,10 +47,7 @@
 #define __ gen()->lir()->
 #endif
 
-// TODO: ARM - Use some recognizable constant which still fits architectural constraints
-#ifdef ARM
-#define PATCHED_ADDR  (204)
-#else
+#ifndef PATCHED_ADDR
 #define PATCHED_ADDR  (max_jint)
 #endif
 
@@ -1599,25 +1597,9 @@
   }
   assert(addr->is_register(), "must be a register at this point");
 
-#ifdef ARM
-  // TODO: ARM - move to platform-dependent code
-  LIR_Opr tmp = FrameMap::R14_opr;
-  if (VM_Version::supports_movw()) {
-    __ move((LIR_Opr)card_table_base, tmp);
-  } else {
-    __ move(new LIR_Address(FrameMap::Rthread_opr, in_bytes(JavaThread::card_table_base_offset()), T_ADDRESS), tmp);
-  }
-
-  CardTableModRefBS* ct = (CardTableModRefBS*)_bs;
-  LIR_Address *card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTableModRefBS::card_shift, 0, T_BYTE);
-  if(((int)ct->byte_map_base & 0xff) == 0) {
-    __ move(tmp, card_addr);
-  } else {
-    LIR_Opr tmp_zero = new_register(T_INT);
-    __ move(LIR_OprFact::intConst(0), tmp_zero);
-    __ move(tmp_zero, card_addr);
-  }
-#else // ARM
+#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER
+  CardTableModRef_post_barrier_helper(addr, card_table_base);
+#else
   LIR_Opr tmp = new_pointer_register();
   if (TwoOperandLIRForm) {
     __ move(addr, tmp);
@@ -1633,7 +1615,7 @@
               new LIR_Address(tmp, load_constant(card_table_base),
                               T_BYTE));
   }
-#endif // ARM
+#endif
 }
 
 
@@ -2121,7 +2103,7 @@
   } else {
 #ifdef X86
     addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type);
-#elif defined(ARM)
+#elif defined(GENERATE_ADDRESS_IS_PREFERRED)
     addr = generate_address(base_op, index_op, log2_scale, 0, dst_type);
 #else
     if (index_op->is_illegal() || log2_scale == 0) {
@@ -2175,6 +2157,9 @@
   LIR_Opr base_op = base.result();
   LIR_Opr index_op = idx.result();
 
+#ifdef GENERATE_ADDRESS_IS_PREFERRED
+  LIR_Address* addr = generate_address(base_op, index_op, log2_scale, 0, x->basic_type());
+#else
 #ifndef _LP64
   if (base_op->type() == T_LONG) {
     base_op = new_register(T_INT);
@@ -2208,6 +2193,7 @@
   }
 
   LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
+#endif // !GENERATE_ADDRESS_IS_PREFERRED
   __ move(value.result(), addr);
 }
 
@@ -2561,7 +2547,7 @@
     // need to free up storage used for OSR entry point
     LIR_Opr osrBuffer = block()->next()->operand();
     BasicTypeList signature;
-    signature.append(T_INT);
+    signature.append(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); // pass a pointer to osrBuffer
     CallingConvention* cc = frame_map()->c_calling_convention(&signature);
     __ move(osrBuffer, cc->args()->at(0));
     __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end),
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -277,6 +277,9 @@
 
   void G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val);
   void CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val);
+#ifdef CARDTABLEMODREF_POST_BARRIER_HELPER
+  void CardTableModRef_post_barrier_helper(LIR_OprDesc* addr, LIR_Const* card_table_base);
+#endif
 
 
   static LIR_Opr result_register_for(ValueType* type, bool callee = false);
@@ -550,6 +553,10 @@
 #ifdef ASSERT
   virtual void do_Assert         (Assert*          x);
 #endif
+
+#ifdef C1_LIRGENERATOR_MD_HPP
+#include C1_LIRGENERATOR_MD_HPP
+#endif
 };
 
 
--- a/src/share/vm/c1/c1_LinearScan.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_LinearScan.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2138,7 +2138,7 @@
         assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
         assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
         LIR_Opr result = LIR_OprFact::double_fpu(interval->assigned_regHi() - pd_first_fpu_reg, assigned_reg - pd_first_fpu_reg);
-#elif defined(ARM)
+#elif defined(ARM32)
         assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
         assert(interval->assigned_regHi() >= pd_first_fpu_reg && interval->assigned_regHi() <= pd_last_fpu_reg, "no fpu register");
         assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
@@ -2727,7 +2727,7 @@
 #ifdef SPARC
       assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
 #endif
-#ifdef ARM
+#ifdef ARM32
       assert(opr->fpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)");
 #endif
 #ifdef PPC
--- a/src/share/vm/c1/c1_Runtime1.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1085,7 +1085,7 @@
 #ifdef ARM
           if((load_klass_or_mirror_patch_id ||
               stub_id == Runtime1::load_appendix_patching_id) &&
-             !VM_Version::supports_movw()) {
+              nativeMovConstReg_at(copy_buff)->is_pc_relative()) {
             nmethod* nm = CodeCache::find_nmethod(instr_pc);
             address addr = NULL;
             assert(nm != NULL, "invalid nmethod_pc");
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -42,7 +42,7 @@
   #define TRACE_BCEA(level, code)
 #endif
 
-// Maintain a map of which aguments a local variable or
+// Maintain a map of which arguments a local variable or
 // stack slot may contain.  In addition to tracking
 // arguments, it tracks two special values, "allocated"
 // which represents any object allocated in the current
@@ -89,8 +89,8 @@
 public:
   ArgumentMap *_vars;
   ArgumentMap *_stack;
-  short _stack_height;
-  short _max_stack;
+  int _stack_height;
+  int _max_stack;
   bool _initialized;
   ArgumentMap empty_map;
 
@@ -318,14 +318,16 @@
     bool must_record_dependencies = false;
     for (i = arg_size - 1; i >= 0; i--) {
       ArgumentMap arg = state.raw_pop();
-      if (!is_argument(arg))
+      // Check if callee arg is a caller arg or an allocated object
+      bool allocated = arg.contains_allocated();
+      if (!(is_argument(arg) || allocated))
         continue;
       for (int j = 0; j < _arg_size; j++) {
         if (arg.contains(j)) {
           _arg_modified[j] |= analyzer._arg_modified[i];
         }
       }
-      if (!is_arg_stack(arg)) {
+      if (!(is_arg_stack(arg) || allocated)) {
         // arguments have already been recognized as escaping
       } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
         set_method_escape(arg);
--- a/src/share/vm/ci/ciTypeFlow.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -36,6 +36,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/compile.hpp"
+#include "opto/node.hpp"
 #include "runtime/deoptimization.hpp"
 #include "utilities/growableArray.hpp"
 
--- a/src/share/vm/classfile/classLoaderData.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/classLoaderData.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -320,27 +320,6 @@
   }
 }
 
-#ifdef ASSERT
-class AllAliveClosure : public OopClosure {
-  BoolObjectClosure* _is_alive_closure;
-  bool _found_dead;
- public:
-  AllAliveClosure(BoolObjectClosure* is_alive_closure) : _is_alive_closure(is_alive_closure), _found_dead(false) {}
-  template <typename T> void do_oop_work(T* p) {
-    T heap_oop = oopDesc::load_heap_oop(p);
-    if (!oopDesc::is_null(heap_oop)) {
-      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-      if (!_is_alive_closure->do_object_b(obj)) {
-        _found_dead = true;
-      }
-    }
-  }
-  void do_oop(oop* p)       { do_oop_work<oop>(p); }
-  void do_oop(narrowOop* p) { do_oop_work<narrowOop>(p); }
-  bool found_dead()         { return _found_dead; }
-};
-#endif
-
 oop ClassLoaderData::keep_alive_object() const {
   assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
   return is_anonymous() ? _klasses->java_mirror() : class_loader();
@@ -350,15 +329,6 @@
   bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
       || is_alive_closure->do_object_b(keep_alive_object());
 
-#ifdef ASSERT
-  if (alive) {
-    AllAliveClosure all_alive_closure(is_alive_closure);
-    KlassToOopClosure klass_closure(&all_alive_closure);
-    const_cast<ClassLoaderData*>(this)->oops_do(&all_alive_closure, &klass_closure, false);
-    assert(!all_alive_closure.found_dead(), err_msg("Found dead oop in alive cld: " PTR_FORMAT, p2i(this)));
-  }
-#endif
-
   return alive;
 }
 
@@ -912,7 +882,7 @@
 }
 
 Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
-  Klass* head = (Klass*)_next_klass;
+  Klass* head = _next_klass;
 
   while (head != NULL) {
     Klass* next = next_klass_in_cldg(head);
--- a/src/share/vm/classfile/classLoaderData.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/classLoaderData.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -307,7 +307,7 @@
 
 // An iterator that distributes Klasses to parallel worker threads.
 class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj {
-  volatile Klass* _next_klass;
+ Klass* volatile _next_klass;
  public:
   ClassLoaderDataGraphKlassIteratorAtomic();
   Klass* next_klass();
--- a/src/share/vm/classfile/defaultMethods.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/defaultMethods.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -731,10 +731,12 @@
     Method* m = iklass->find_method(_method_name, _method_signature);
     // private interface methods are not candidates for default methods
     // invokespecial to private interface methods doesn't use default method logic
+    // private class methods are not candidates for default methods,
+    // private methods do not override default methods, so need to perform
+    // default method inheritance without including private methods
     // The overpasses are your supertypes' errors, we do not include them
     // future: take access controls into account for superclass methods
-    if (m != NULL && !m->is_static() && !m->is_overpass() &&
-         (!iklass->is_interface() || m->is_public())) {
+    if (m != NULL && !m->is_static() && !m->is_overpass() && !m->is_private()) {
       if (_family == NULL) {
         _family = new StatefulMethodFamily();
       }
@@ -745,6 +747,9 @@
       } else {
         // This is the rule that methods in classes "win" (bad word) over
         // methods in interfaces. This works because of single inheritance
+        // private methods in classes do not "win", they will be found
+        // first on searching, but overriding for invokevirtual needs
+        // to find default method candidates for the same signature
         _family->set_target_if_empty(m);
       }
     }
@@ -1091,6 +1096,7 @@
     }
     // update idnum for new location
     merged_methods->at(i)->set_method_idnum(i);
+    merged_methods->at(i)->set_orig_method_idnum(i);
   }
 
   // Verify correct order
--- a/src/share/vm/classfile/javaClasses.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/javaClasses.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1278,7 +1278,8 @@
 }
 
 static inline bool version_matches(Method* method, int version) {
-  return (method->constants()->version() == version && version < MAX_VERSION);
+  assert(version < MAX_VERSION, "version is too big");
+  return method != NULL && (method->constants()->version() == version);
 }
 
 static inline int get_line_number(Method* method, int bci) {
@@ -1308,6 +1309,7 @@
   typeArrayOop    _methods;
   typeArrayOop    _bcis;
   objArrayOop     _mirrors;
+  typeArrayOop    _cprefs; // needed to insulate method name against redefinition
   int             _index;
   No_Safepoint_Verifier _nsv;
 
@@ -1315,8 +1317,9 @@
 
   enum {
     trace_methods_offset = java_lang_Throwable::trace_methods_offset,
-    trace_bcis_offset = java_lang_Throwable::trace_bcis_offset,
+    trace_bcis_offset    = java_lang_Throwable::trace_bcis_offset,
     trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
+    trace_cprefs_offset  = java_lang_Throwable::trace_cprefs_offset,
     trace_next_offset    = java_lang_Throwable::trace_next_offset,
     trace_size           = java_lang_Throwable::trace_size,
     trace_chunk_size     = java_lang_Throwable::trace_chunk_size
@@ -1338,9 +1341,14 @@
     assert(mirrors != NULL, "mirror array should be initialized in backtrace");
     return mirrors;
   }
+  static typeArrayOop get_cprefs(objArrayHandle chunk) {
+    typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset));
+    assert(cprefs != NULL, "cprefs array should be initialized in backtrace");
+    return cprefs;
+  }
 
   // constructor for new backtrace
-  BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) {
+  BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) {
     expand(CHECK);
     _backtrace = _head;
     _index = 0;
@@ -1350,6 +1358,7 @@
     _methods = get_methods(backtrace);
     _bcis = get_bcis(backtrace);
     _mirrors = get_mirrors(backtrace);
+    _cprefs = get_cprefs(backtrace);
     assert(_methods->length() == _bcis->length() &&
            _methods->length() == _mirrors->length(),
            "method and source information arrays should match");
@@ -1375,17 +1384,22 @@
     objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK);
     objArrayHandle new_mirrors(THREAD, mirrors);
 
+    typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK);
+    typeArrayHandle new_cprefs(THREAD, cprefs);
+
     if (!old_head.is_null()) {
       old_head->obj_at_put(trace_next_offset, new_head());
     }
     new_head->obj_at_put(trace_methods_offset, new_methods());
     new_head->obj_at_put(trace_bcis_offset, new_bcis());
     new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
+    new_head->obj_at_put(trace_cprefs_offset, new_cprefs());
 
     _head    = new_head();
     _methods = new_methods();
     _bcis = new_bcis();
     _mirrors = new_mirrors();
+    _cprefs  = new_cprefs();
     _index = 0;
   }
 
@@ -1405,8 +1419,9 @@
       method = mhandle();
     }
 
-    _methods->short_at_put(_index, method->method_idnum());
+    _methods->short_at_put(_index, method->orig_method_idnum());
     _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version()));
+    _cprefs->short_at_put(_index, method->name_index());
 
     // We need to save the mirrors in the backtrace to keep the class
     // from being unloaded while we still have this stack trace.
@@ -1419,27 +1434,26 @@
 
 // Print stack trace element to resource allocated buffer
 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
-                                  int method_id, int version, int bci) {
+                                  int method_id, int version, int bci, int cpref) {
 
   // Get strings and string lengths
   InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
   const char* klass_name  = holder->external_name();
   int buf_len = (int)strlen(klass_name);
 
-  // The method id may point to an obsolete method, can't get more stack information
-  Method* method = holder->method_with_idnum(method_id);
-  if (method == NULL) {
-    char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
-    // This is what the java code prints in this case - added Redefined
-    sprintf(buf, "\tat %s.null (Redefined)", klass_name);
-    return buf;
-  }
-
-  char* method_name = method->name()->as_C_string();
+  Method* method = holder->method_with_orig_idnum(method_id, version);
+
+  // The method can be NULL if the requested class version is gone
+  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
+  char* method_name = sym->as_C_string();
   buf_len += (int)strlen(method_name);
 
+  // Use a specific ik version as a holder since the mirror might
+  // refer to a version that is now obsolete and no longer accessible
+  // via the previous versions list.
+  holder = holder->get_klass_version(version);
   char* source_file_name = NULL;
-  if (version_matches(method, version)) {
+  if (holder != NULL) {
     Symbol* source = holder->source_file_name();
     if (source != NULL) {
       source_file_name = source->as_C_string();
@@ -1481,17 +1495,18 @@
 }
 
 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror,
-                                              int method_id, int version, int bci) {
+                                              int method_id, int version, int bci, int cpref) {
   ResourceMark rm;
-  char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci);
+  char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref);
   st->print_cr("%s", buf);
 }
 
 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) {
   Handle mirror = method->method_holder()->java_mirror();
-  int method_id = method->method_idnum();
+  int method_id = method->orig_method_idnum();
   int version = method->constants()->version();
-  print_stack_element(st, mirror, method_id, version, bci);
+  int cpref = method->name_index();
+  print_stack_element(st, mirror, method_id, version, bci, cpref);
 }
 
 const char* java_lang_Throwable::no_stack_trace_message() {
@@ -1516,6 +1531,7 @@
       typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result));
       typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result));
       objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result));
+      typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result));
 
       int length = methods()->length();
       for (int index = 0; index < length; index++) {
@@ -1525,7 +1541,8 @@
         int method = methods->short_at(index);
         int version = version_at(bcis->int_at(index));
         int bci = bci_at(bcis->int_at(index));
-        print_stack_element(st, mirror, method, version, bci);
+        int cpref = cprefs->short_at(index);
+        print_stack_element(st, mirror, method, version, bci, cpref);
       }
       result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset)));
     }
@@ -1809,29 +1826,30 @@
   if (chunk == NULL) {
     THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
   }
-  // Get method id, bci, version and mirror from chunk
+  // Get method id, bci, version, mirror and cpref from chunk
   typeArrayOop methods = BacktraceBuilder::get_methods(chunk);
   typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk);
   objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk);
+  typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk);
 
   assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check");
 
   int method = methods->short_at(chunk_index);
   int version = version_at(bcis->int_at(chunk_index));
   int bci = bci_at(bcis->int_at(chunk_index));
+  int cpref = cprefs->short_at(chunk_index);
   Handle mirror(THREAD, mirrors->obj_at(chunk_index));
 
   // Chunk can be partial full
   if (mirror.is_null()) {
     THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
   }
-
-  oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0);
+  oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0);
   return element;
 }
 
 oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
-                                        int version, int bci, TRAPS) {
+                                        int version, int bci, int cpref, TRAPS) {
   // Allocate java.lang.StackTraceElement instance
   Klass* k = SystemDictionary::StackTraceElement_klass();
   assert(k != NULL, "must be loaded in 1.4+");
@@ -1848,17 +1866,13 @@
   oop classname = StringTable::intern((char*) str, CHECK_0);
   java_lang_StackTraceElement::set_declaringClass(element(), classname);
 
-  Method* method = holder->method_with_idnum(method_id);
-  // Method on stack may be obsolete because it was redefined so cannot be
-  // found by idnum.
-  if (method == NULL) {
-    // leave name and fileName null
-    java_lang_StackTraceElement::set_lineNumber(element(), -1);
-    return element();
-  }
+  Method* method = holder->method_with_orig_idnum(method_id, version);
+
+  // The method can be NULL if the requested class version is gone
+  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
 
   // Fill in method name
-  oop methodname = StringTable::intern(method->name(), CHECK_0);
+  oop methodname = StringTable::intern(sym, CHECK_0);
   java_lang_StackTraceElement::set_methodName(element(), methodname);
 
   if (!version_matches(method, version)) {
@@ -1867,6 +1881,11 @@
     java_lang_StackTraceElement::set_lineNumber(element(), -1);
   } else {
     // Fill in source file name and line number.
+    // Use a specific ik version as a holder since the mirror might
+    // refer to a version that is now obsolete and no longer accessible
+    // via the previous versions list.
+    holder = holder->get_klass_version(version);
+    assert(holder != NULL, "sanity check");
     Symbol* source = holder->source_file_name();
     if (ShowHiddenFrames && source == NULL)
       source = vmSymbols::unknown_class_name();
@@ -1881,8 +1900,9 @@
 
 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
   Handle mirror (THREAD, method->method_holder()->java_mirror());
-  int method_id = method->method_idnum();
-  return create(mirror, method_id, method->constants()->version(), bci, THREAD);
+  int method_id = method->orig_method_idnum();
+  int cpref = method->name_index();
+  return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD);
 }
 
 void java_lang_reflect_AccessibleObject::compute_offsets() {
--- a/src/share/vm/classfile/javaClasses.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/javaClasses.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -484,8 +484,9 @@
     trace_methods_offset = 0,
     trace_bcis_offset    = 1,
     trace_mirrors_offset = 2,
-    trace_next_offset    = 3,
-    trace_size           = 4,
+    trace_cprefs_offset  = 3,
+    trace_next_offset    = 4,
+    trace_size           = 5,
     trace_chunk_size     = 32
   };
 
@@ -496,7 +497,7 @@
   static int static_unassigned_stacktrace_offset;
 
   // Printing
-  static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci);
+  static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci, int cpref);
   // StackTrace (programmatic access, new since 1.4)
   static void clear_stacktrace(oop throwable);
   // No stack trace available
@@ -517,7 +518,7 @@
   static oop message(Handle throwable);
   static void set_message(oop throwable, oop value);
   static void print_stack_element(outputStream *st, Handle mirror, int method,
-                                  int version, int bci);
+                                  int version, int bci, int cpref);
   static void print_stack_element(outputStream *st, methodHandle method, int bci);
   static void print_stack_usage(Handle stream);
 
@@ -1326,7 +1327,7 @@
   static void set_lineNumber(oop element, int value);
 
   // Create an instance of StackTraceElement
-  static oop create(Handle mirror, int method, int version, int bci, TRAPS);
+  static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS);
   static oop create(methodHandle method, int bci, TRAPS);
 
   // Debugging
--- a/src/share/vm/classfile/systemDictionary.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/systemDictionary.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1907,11 +1907,12 @@
   InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
   InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
 
-  initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
+  initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK);
   InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
   InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
   InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
   InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
+  InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
 
   // JSR 292 classes
   WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -128,6 +128,7 @@
   do_klass(WeakReference_klass,                         java_lang_ref_WeakReference,               Pre                 ) \
   do_klass(FinalReference_klass,                        java_lang_ref_FinalReference,              Pre                 ) \
   do_klass(PhantomReference_klass,                      java_lang_ref_PhantomReference,            Pre                 ) \
+  do_klass(Cleaner_klass,                               sun_misc_Cleaner,                          Pre                 ) \
   do_klass(Finalizer_klass,                             java_lang_ref_Finalizer,                   Pre                 ) \
                                                                                                                          \
   do_klass(Thread_klass,                                java_lang_Thread,                          Pre                 ) \
--- a/src/share/vm/classfile/verifier.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/verifier.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -655,6 +655,7 @@
 
 
     bool this_uninit = false;  // Set to true when invokespecial <init> initialized 'this'
+    bool verified_exc_handlers = false;
 
     // Merge with the next instruction
     {
@@ -686,6 +687,18 @@
         }
       }
 
+      // Look for possible jump target in exception handlers and see if it
+      // matches current_frame.  Do this check here for astore*, dstore*,
+      // fstore*, istore*, and lstore* opcodes because they can change the type
+      // state by adding a local.  JVM Spec says that the incoming type state
+      // should be used for this check.  So, do the check here before a possible
+      // local is added to the type state.
+      if (Bytecodes::is_store_into_local(opcode) && bci >= ex_min && bci < ex_max) {
+        verify_exception_handler_targets(
+          bci, this_uninit, &current_frame, &stackmap_table, CHECK_VERIFY(this));
+        verified_exc_handlers = true;
+      }
+
       switch (opcode) {
         case Bytecodes::_nop :
           no_control_flow = false; break;
@@ -1553,14 +1566,14 @@
         case Bytecodes::_invokespecial :
         case Bytecodes::_invokestatic :
           verify_invoke_instructions(
-            &bcs, code_length, &current_frame,
-            &this_uninit, return_type, cp, CHECK_VERIFY(this));
+            &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
+            &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_invokeinterface :
         case Bytecodes::_invokedynamic :
           verify_invoke_instructions(
-            &bcs, code_length, &current_frame,
-            &this_uninit, return_type, cp, CHECK_VERIFY(this));
+            &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
+            &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_new :
         {
@@ -1662,9 +1675,13 @@
       }  // end switch
     }  // end Merge with the next instruction
 
-    // Look for possible jump target in exception handlers and see if it
-    // matches current_frame
-    if (bci >= ex_min && bci < ex_max) {
+    // Look for possible jump target in exception handlers and see if it matches
+    // current_frame.  Don't do this check if it has already been done (for
+    // ([a,d,f,i,l]store* opcodes).  This check cannot be done earlier because
+    // opcodes, such as invokespecial, may set the this_uninit flag.
+    assert(!(verified_exc_handlers && this_uninit),
+      "Exception handler targets got verified before this_uninit got set");
+    if (!verified_exc_handlers && bci >= ex_min && bci < ex_max) {
       verify_exception_handler_targets(
         bci, this_uninit, &current_frame, &stackmap_table, CHECK_VERIFY(this));
     }
@@ -2232,14 +2249,20 @@
 }
 
 // Look at the method's handlers.  If the bci is in the handler's try block
-// then check if the handler_pc is already on the stack.  If not, push it.
+// then check if the handler_pc is already on the stack.  If not, push it
+// unless the handler has already been scanned.
 void ClassVerifier::push_handlers(ExceptionTable* exhandlers,
+                                  GrowableArray<u4>* handler_list,
                                   GrowableArray<u4>* handler_stack,
                                   u4 bci) {
   int exlength = exhandlers->length();
   for(int x = 0; x < exlength; x++) {
     if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) {
-      handler_stack->append_if_missing(exhandlers->handler_pc(x));
+      u4 exhandler_pc = exhandlers->handler_pc(x);
+      if (!handler_list->contains(exhandler_pc)) {
+        handler_stack->append_if_missing(exhandler_pc);
+        handler_list->append(exhandler_pc);
+      }
     }
   }
 }
@@ -2257,6 +2280,10 @@
   GrowableArray<u4>* bci_stack = new GrowableArray<u4>(30);
   // Create stack for handlers for try blocks containing this handler.
   GrowableArray<u4>* handler_stack = new GrowableArray<u4>(30);
+  // Create list of handlers that have been pushed onto the handler_stack
+  // so that handlers embedded inside of their own TRY blocks only get
+  // scanned once.
+  GrowableArray<u4>* handler_list = new GrowableArray<u4>(30);
   // Create list of visited branch opcodes (goto* and if*).
   GrowableArray<u4>* visited_branches = new GrowableArray<u4>(30);
   ExceptionTable exhandlers(_method());
@@ -2275,7 +2302,7 @@
 
     // If the bytecode is in a TRY block, push its handlers so they
     // will get parsed.
-    push_handlers(&exhandlers, handler_stack, bci);
+    push_handlers(&exhandlers, handler_list, handler_stack, bci);
 
     switch (opcode) {
       case Bytecodes::_if_icmpeq:
@@ -2408,8 +2435,9 @@
 
 void ClassVerifier::verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
-    StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
-    constantPoolHandle cp, TRAPS) {
+    StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+    bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+    TRAPS) {
   u2 bci = bcs->bci();
   VerificationType type = current_frame->pop_stack(
     VerificationType::reference_check(), CHECK_VERIFY(this));
@@ -2425,28 +2453,36 @@
       return;
     }
 
-    // Check if this call is done from inside of a TRY block.  If so, make
-    // sure that all catch clause paths end in a throw.  Otherwise, this
-    // can result in returning an incomplete object.
-    ExceptionTable exhandlers(_method());
-    int exlength = exhandlers.length();
-    for(int i = 0; i < exlength; i++) {
-      u2 start_pc = exhandlers.start_pc(i);
-      u2 end_pc = exhandlers.end_pc(i);
+    // If this invokespecial call is done from inside of a TRY block then make
+    // sure that all catch clause paths end in a throw.  Otherwise, this can
+    // result in returning an incomplete object.
+    if (in_try_block) {
+      ExceptionTable exhandlers(_method());
+      int exlength = exhandlers.length();
+      for(int i = 0; i < exlength; i++) {
+        u2 start_pc = exhandlers.start_pc(i);
+        u2 end_pc = exhandlers.end_pc(i);
 
-      if (bci >= start_pc && bci < end_pc) {
-        if (!ends_in_athrow(exhandlers.handler_pc(i))) {
-          verify_error(ErrorContext::bad_code(bci),
-            "Bad <init> method call from after the start of a try block");
-          return;
-        } else if (VerboseVerification) {
-          ResourceMark rm;
-          tty->print_cr(
-            "Survived call to ends_in_athrow(): %s",
-                        current_class()->name()->as_C_string());
+        if (bci >= start_pc && bci < end_pc) {
+          if (!ends_in_athrow(exhandlers.handler_pc(i))) {
+            verify_error(ErrorContext::bad_code(bci),
+              "Bad <init> method call from after the start of a try block");
+            return;
+          } else if (VerboseVerification) {
+            ResourceMark rm;
+            tty->print_cr(
+              "Survived call to ends_in_athrow(): %s",
+              current_class()->name()->as_C_string());
+          }
         }
       }
-    }
+
+      // Check the exception handler target stackmaps with the locals from the
+      // incoming stackmap (before initialize_object() changes them to outgoing
+      // state).
+      verify_exception_handler_targets(bci, true, current_frame,
+                                       stackmap_table, CHECK_VERIFY(this));
+    } // in_try_block
 
     current_frame->initialize_object(type, current_type());
     *this_uninit = true;
@@ -2479,8 +2515,7 @@
     // of the current class.
     VerificationType objectref_type = new_class_type;
     if (name_in_supers(ref_class_type.name(), current_class())) {
-      Klass* ref_klass = load_class(
-        ref_class_type.name(), CHECK_VERIFY(this));
+      Klass* ref_klass = load_class(ref_class_type.name(), CHECK);
       Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method(
         vmSymbols::object_initializer_name(),
         cp->signature_ref_at(bcs->get_index_u2()), Klass::normal);
@@ -2500,6 +2535,13 @@
         }
       }
     }
+    // Check the exception handler target stackmaps with the locals from the
+    // incoming stackmap (before initialize_object() changes them to outgoing
+    // state).
+    if (in_try_block) {
+      verify_exception_handler_targets(bci, *this_uninit, current_frame,
+                                       stackmap_table, CHECK_VERIFY(this));
+    }
     current_frame->initialize_object(type, new_class_type);
   } else {
     verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
@@ -2528,8 +2570,8 @@
 
 void ClassVerifier::verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
-    bool *this_uninit, VerificationType return_type,
-    constantPoolHandle cp, TRAPS) {
+    bool in_try_block, bool *this_uninit, VerificationType return_type,
+    constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
   // Make sure the constant pool item is the right type
   u2 index = bcs->get_index_u2();
   Bytecodes::Code opcode = bcs->raw_code();
@@ -2699,7 +2741,8 @@
       opcode != Bytecodes::_invokedynamic) {
     if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
       verify_invoke_init(bcs, index, ref_class_type, current_frame,
-        code_length, this_uninit, cp, CHECK_VERIFY(this));
+        code_length, in_try_block, this_uninit, cp, stackmap_table,
+        CHECK_VERIFY(this));
     } else {   // other methods
       // Ensures that target class is assignable to method class.
       if (opcode == Bytecodes::_invokespecial) {
--- a/src/share/vm/classfile/verifier.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/verifier.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -301,12 +301,14 @@
 
   void verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
-    StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
-    constantPoolHandle cp, TRAPS);
+    StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+    bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+    TRAPS);
 
-  // Used by ends_in_athrow() to push all handlers that contain bci onto
-  // the handler_stack, if the handler is not already on the stack.
+  // Used by ends_in_athrow() to push all handlers that contain bci onto the
+  // handler_stack, if the handler has not already been pushed on the stack.
   void push_handlers(ExceptionTable* exhandlers,
+                     GrowableArray<u4>* handler_list,
                      GrowableArray<u4>* handler_stack,
                      u4 bci);
 
@@ -316,8 +318,8 @@
 
   void verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
-    bool* this_uninit, VerificationType return_type,
-    constantPoolHandle cp, TRAPS);
+    bool in_try_block, bool* this_uninit, VerificationType return_type,
+    constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
 
   VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
   void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -79,6 +79,7 @@
   template(java_lang_ref_WeakReference,               "java/lang/ref/WeakReference")              \
   template(java_lang_ref_FinalReference,              "java/lang/ref/FinalReference")             \
   template(java_lang_ref_PhantomReference,            "java/lang/ref/PhantomReference")           \
+  template(sun_misc_Cleaner,                          "sun/misc/Cleaner")                         \
   template(java_lang_ref_Finalizer,                   "java/lang/ref/Finalizer")                  \
   template(java_lang_reflect_AccessibleObject,        "java/lang/reflect/AccessibleObject")       \
   template(java_lang_reflect_Method,                  "java/lang/reflect/Method")                 \
--- a/src/share/vm/code/dependencies.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/code/dependencies.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -560,7 +560,7 @@
       put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value());
     } else if (arg.is_method()) {
       what = "method ";
-      put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value());
+      put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL);
     } else if (arg.is_klass()) {
       what = "class  ";
     } else {
@@ -811,7 +811,13 @@
     assert((uint)n <= (uint)_num_participants, "oob");
     Method* fm = _found_methods[n];
     assert(n == _num_participants || fm != NULL, "proper usage");
-    assert(fm == NULL || fm->method_holder() == _participants[n], "sanity");
+    if (fm != NULL && fm->method_holder() != _participants[n]) {
+      // Default methods from interfaces can be added to classes. In
+      // that case the holder of the method is not the class but the
+      // interface where it's defined.
+      assert(fm->is_default_method(), "sanity");
+      return NULL;
+    }
     return fm;
   }
 
@@ -845,8 +851,8 @@
         // Static methods don't override non-static so punt
         return true;
       }
-      if (   !Dependencies::is_concrete_method(lm)
-          && !Dependencies::is_concrete_method(m)
+      if (   !Dependencies::is_concrete_method(lm, k)
+          && !Dependencies::is_concrete_method(m, ctxk)
           && lm->method_holder()->is_subtype_of(m->method_holder()))
         // Method m is overridden by lm, but both are non-concrete.
         return true;
@@ -882,8 +888,17 @@
     } else if (!k->oop_is_instance()) {
       return false; // no methods to find in an array type
     } else {
-      Method* m = InstanceKlass::cast(k)->find_method(_name, _signature);
-      if (m == NULL || !Dependencies::is_concrete_method(m))  return false;
+      // Search class hierarchy first.
+      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+      if (!Dependencies::is_concrete_method(m, k)) {
+        // Check interface defaults also, if any exist.
+        Array<Method*>* default_methods = InstanceKlass::cast(k)->default_methods();
+        if (default_methods == NULL)
+            return false;
+        m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature);
+        if (!Dependencies::is_concrete_method(m, NULL))
+            return false;
+      }
       _found_methods[_num_participants] = m;
       // Note:  If add_participant(k) is called,
       // the method m will already be memoized for it.
@@ -1176,15 +1191,17 @@
   return true;
 }
 
-bool Dependencies::is_concrete_method(Method* m) {
-  // Statics are irrelevant to virtual call sites.
-  if (m->is_static())  return false;
-
-  // We could also return false if m does not yet appear to be
-  // executed, if the VM version supports this distinction also.
-  // Default methods are considered "concrete" as well.
-  return !m->is_abstract() &&
-         !m->is_overpass(); // error functions aren't concrete
+bool Dependencies::is_concrete_method(Method* m, Klass * k) {
+  // NULL is not a concrete method,
+  // statics are irrelevant to virtual call sites,
+  // abstract methods are not concrete,
+  // overpass (error) methods are not concrete if k is abstract
+  //
+  // note "true" is conservative answer --
+  //     overpass clause is false if k == NULL, implies return true if
+  //     answer depends on overpass clause.
+  return ! ( m == NULL || m -> is_static() || m -> is_abstract() ||
+             m->is_overpass() && k != NULL && k -> is_abstract() );
 }
 
 
@@ -1209,16 +1226,6 @@
   return true;
 }
 
-bool Dependencies::is_concrete_method(ciMethod* m) {
-  // Statics are irrelevant to virtual call sites.
-  if (m->is_static())  return false;
-
-  // We could also return false if m does not yet appear to be
-  // executed, if the VM version supports this distinction also.
-  return !m->is_abstract();
-}
-
-
 bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
   return k->has_finalizable_subclass();
 }
@@ -1432,7 +1439,7 @@
   Klass* wit = wf.find_witness_definer(ctxk);
   if (wit != NULL)  return NULL;  // Too many witnesses.
   Method* fm = wf.found_method(0);  // Will be NULL if num_parts == 0.
-  if (Dependencies::is_concrete_method(m)) {
+  if (Dependencies::is_concrete_method(m, ctxk)) {
     if (fm == NULL) {
       // It turns out that m was always the only implementation.
       fm = m;
@@ -1462,61 +1469,6 @@
   return wf.find_witness_definer(ctxk, changes);
 }
 
-// Find the set of all non-abstract methods under ctxk that match m[0].
-// (The method m[0] must be defined or inherited in ctxk.)
-// Include m itself in the set, unless it is abstract.
-// Fill the given array m[0..(mlen-1)] with this set, and return the length.
-// (The length may be zero if no concrete methods are found anywhere.)
-// If there are too many concrete methods to fit in marray, return -1.
-int Dependencies::find_exclusive_concrete_methods(Klass* ctxk,
-                                                  int mlen,
-                                                  Method* marray[]) {
-  Method* m0 = marray[0];
-  ClassHierarchyWalker wf(m0);
-  assert(wf.check_method_context(ctxk, m0), "proper context");
-  wf.record_witnesses(mlen);
-  bool participants_hide_witnesses = true;
-  Klass* wit = wf.find_witness_definer(ctxk);
-  if (wit != NULL)  return -1;  // Too many witnesses.
-  int num = wf.num_participants();
-  assert(num <= mlen, "oob");
-  // Keep track of whether m is also part of the result set.
-  int mfill = 0;
-  assert(marray[mfill] == m0, "sanity");
-  if (Dependencies::is_concrete_method(m0))
-    mfill++;  // keep m0 as marray[0], the first result
-  for (int i = 0; i < num; i++) {
-    Method* fm = wf.found_method(i);
-    if (fm == m0)  continue;  // Already put this guy in the list.
-    if (mfill == mlen) {
-      return -1;              // Oops.  Too many methods after all!
-    }
-    marray[mfill++] = fm;
-  }
-#ifndef PRODUCT
-  // Make sure the dependency mechanism will pass this discovery:
-  if (VerifyDependencies) {
-    // Turn off dependency tracing while actually testing deps.
-    FlagSetting fs(TraceDependencies, false);
-    switch (mfill) {
-    case 1:
-      guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]),
-                "verify dep.");
-      break;
-    case 2:
-      guarantee(NULL == (void *)
-                check_exclusive_concrete_methods(ctxk, marray[0], marray[1]),
-                "verify dep.");
-      break;
-    default:
-      ShouldNotReachHere();  // mlen > 2 yet supported
-    }
-  }
-#endif //PRODUCT
-  return mfill;
-}
-
-
 Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) {
   Klass* search_at = ctxk;
   if (changes != NULL)
@@ -1524,7 +1476,6 @@
   return find_finalizable_subclass(search_at);
 }
 
-
 Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
   assert(call_site    ->is_a(SystemDictionary::CallSite_klass()),     "sanity");
   assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
--- a/src/share/vm/code/dependencies.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/code/dependencies.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -287,7 +287,7 @@
   // In that case, there would be a middle ground between concrete
   // and abstract (as defined by the Java language and VM).
   static bool is_concrete_klass(Klass* k);    // k is instantiable
-  static bool is_concrete_method(Method* m);  // m is invocable
+  static bool is_concrete_method(Method* m, Klass* k);  // m is invocable
   static Klass* find_finalizable_subclass(Klass* k);
 
   // These versions of the concreteness queries work through the CI.
@@ -301,7 +301,6 @@
   // not go back into the VM to get their value; they must cache the
   // bit in the CI, either eagerly or lazily.)
   static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable
-  static bool is_concrete_method(ciMethod* m);       // m appears invocable
   static bool has_finalizable_subclass(ciInstanceKlass* k);
 
   // As a general rule, it is OK to compile under the assumption that
@@ -348,7 +347,6 @@
   static Klass*    find_unique_concrete_subtype(Klass* ctxk);
   static Method*   find_unique_concrete_method(Klass* ctxk, Method* m);
   static int       find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]);
-  static int       find_exclusive_concrete_methods(Klass* ctxk, int mlen, Method* m[]);
 
   // Create the encoding which will be stored in an nmethod.
   void encode_content_bytes();
--- a/src/share/vm/code/vmreg.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/code/vmreg.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +32,17 @@
 #ifdef COMPILER2
 #include "opto/adlcVMDeps.hpp"
 #include "utilities/ostream.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined ADGLOBALS_MD_HPP
+# include ADGLOBALS_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/adGlobals_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/adGlobals_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/adGlobals_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/adGlobals_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/adGlobals_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/adGlobals_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/adGlobals_ppc_64.hpp"
 #endif
 #endif
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -598,7 +598,7 @@
   _collector_policy(cp),
   _should_unload_classes(CMSClassUnloadingEnabled),
   _concurrent_cycles_since_last_unload(0),
-  _roots_scanning_options(SharedHeap::SO_None),
+  _roots_scanning_options(GenCollectedHeap::SO_None),
   _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()),
@@ -738,7 +738,7 @@
   // Support for parallelizing survivor space rescan
   if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
     const size_t max_plab_samples =
-      ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize;
+      ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
 
     _survivor_plab_array  = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
     _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
@@ -796,6 +796,12 @@
   _inter_sweep_timer.start();  // start of time
 }
 
+size_t CMSCollector::plab_sample_minimum_size() {
+  // The default value of MinTLABSize is 2k, but there is
+  // no way to get the default value if the flag has been overridden.
+  return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
+}
+
 const char* ConcurrentMarkSweepGeneration::name() const {
   return "concurrent mark-sweep generation";
 }
@@ -3062,7 +3068,7 @@
   gch->gen_process_roots(_cmsGen->level(),
                          true,   // younger gens are roots
                          true,   // activate StrongRootsScope
-                         SharedHeap::ScanningOption(roots_scanning_options()),
+                         GenCollectedHeap::ScanningOption(roots_scanning_options()),
                          should_unload_classes(),
                          &notOlder,
                          NULL,
@@ -3130,7 +3136,7 @@
   gch->gen_process_roots(_cmsGen->level(),
                          true,   // younger gens are roots
                          true,   // activate StrongRootsScope
-                         SharedHeap::ScanningOption(roots_scanning_options()),
+                         GenCollectedHeap::ScanningOption(roots_scanning_options()),
                          should_unload_classes(),
                          &notOlder,
                          NULL,
@@ -3321,7 +3327,7 @@
 void CMSCollector::setup_cms_unloading_and_verification_state() {
   const  bool should_verify =   VerifyBeforeGC || VerifyAfterGC || VerifyDuringGC
                              || VerifyBeforeExit;
-  const  int  rso           =   SharedHeap::SO_AllCodeCache;
+  const  int  rso           =   GenCollectedHeap::SO_AllCodeCache;
 
   // We set the proper root for this CMS cycle here.
   if (should_unload_classes()) {   // Should unload classes this cycle
@@ -3747,7 +3753,7 @@
       gch->gen_process_roots(_cmsGen->level(),
                              true,   // younger gens are roots
                              true,   // activate StrongRootsScope
-                             SharedHeap::ScanningOption(roots_scanning_options()),
+                             GenCollectedHeap::ScanningOption(roots_scanning_options()),
                              should_unload_classes(),
                              &notOlder,
                              NULL,
@@ -5248,13 +5254,13 @@
   gch->gen_process_roots(_collector->_cmsGen->level(),
                          false,     // yg was scanned above
                          false,     // this is parallel code
-                         SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+                         GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
                          _collector->should_unload_classes(),
                          &par_mri_cl,
                          NULL,
                          &cld_closure);
   assert(_collector->should_unload_classes()
-         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_AllCodeCache),
+         || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   _timer.stop();
   if (PrintCMSStatistics != 0) {
@@ -5384,14 +5390,14 @@
   gch->gen_process_roots(_collector->_cmsGen->level(),
                          false,     // yg was scanned above
                          false,     // this is parallel code
-                         SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+                         GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
                          _collector->should_unload_classes(),
                          &par_mrias_cl,
                          NULL,
                          NULL);     // The dirty klasses will be handled below
 
   assert(_collector->should_unload_classes()
-         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_AllCodeCache),
+         || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   _timer.stop();
   if (PrintCMSStatistics != 0) {
@@ -5976,14 +5982,14 @@
     gch->gen_process_roots(_cmsGen->level(),
                            true,  // younger gens as roots
                            false, // use the local StrongRootsScope
-                           SharedHeap::ScanningOption(roots_scanning_options()),
+                           GenCollectedHeap::ScanningOption(roots_scanning_options()),
                            should_unload_classes(),
                            &mrias_cl,
                            NULL,
                            NULL); // The dirty klasses will be handled below
 
     assert(should_unload_classes()
-           || (roots_scanning_options() & SharedHeap::SO_AllCodeCache),
+           || (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
            "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   }
 
@@ -6628,7 +6634,6 @@
 }
 
 void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
-  gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
   GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer_cm->gc_id());
   TraceCollectorStats tcs(counters());
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -764,6 +764,10 @@
   size_t*    _cursor;
   ChunkArray* _survivor_plab_array;
 
+  // A bounded minimum size of PLABs, should not return too small values since
+  // this will affect the size of the data structures used for parallel young gen rescan
+  size_t plab_sample_minimum_size();
+
   // Support for marking stack overflow handling
   bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
   bool par_take_from_overflow_list(size_t num,
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,8 +130,8 @@
 class VM_GenCollectFullConcurrent: public VM_GC_Operation {
   bool _disabled_icms;
  public:
-  VM_GenCollectFullConcurrent(unsigned int gc_count_before,
-                              unsigned int full_gc_count_before,
+  VM_GenCollectFullConcurrent(uint gc_count_before,
+                              uint full_gc_count_before,
                               GCCause::Cause gc_cause)
     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
       _disabled_icms(false)
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
   nonstatic_field(LinearAllocBlock,            _word_size,                                    size_t)                                \
   nonstatic_field(AFLBinaryTreeDictionary,     _total_size,                                   size_t)                                \
   nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   AFLBinaryTreeDictionary*)              \
-  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList<FreeChunk>)                   \
+  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           AdaptiveFreeList<FreeChunk>)           \
   nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
 
 
--- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,13 @@
     // active field set to true.
     PtrQueue(qset_, perm, true /* active */) { }
 
+  // Flush before destroying; queue may be used to capture pending work while
+  // doing something else, with auto-flush on completion.
+  ~DirtyCardQueue() { if (!is_permanent()) flush(); }
+
+  // Process queue entries and release resources.
+  void flush() { flush_impl(); }
+
   // Apply the closure to all elements, and reset the index to make the
   // buffer empty.  If a closure application returns "false", return
   // "false" immediately, halting the iteration.  If "consume" is true,
--- a/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -254,25 +254,23 @@
 HeapRegion* SurvivorGCAllocRegion::allocate_new_region(size_t word_size,
                                                        bool force) {
   assert(!force, "not supported for GC alloc regions");
-  return _g1h->new_gc_alloc_region(word_size, count(), GCAllocForSurvived);
+  return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Young);
 }
 
 void SurvivorGCAllocRegion::retire_region(HeapRegion* alloc_region,
                                           size_t allocated_bytes) {
-  _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes,
-                               GCAllocForSurvived);
+  _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Young);
 }
 
 HeapRegion* OldGCAllocRegion::allocate_new_region(size_t word_size,
                                                   bool force) {
   assert(!force, "not supported for GC alloc regions");
-  return _g1h->new_gc_alloc_region(word_size, count(), GCAllocForTenured);
+  return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Old);
 }
 
 void OldGCAllocRegion::retire_region(HeapRegion* alloc_region,
                                      size_t allocated_bytes) {
-  _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes,
-                               GCAllocForTenured);
+  _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Old);
 }
 
 HeapRegion* OldGCAllocRegion::release() {
--- a/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -59,7 +59,7 @@
       !(retained_region->top() == retained_region->end()) &&
       !retained_region->is_empty() &&
       !retained_region->isHumongous()) {
-    retained_region->record_top_and_timestamp();
+    retained_region->record_timestamp();
     // The retained region was added to the old region set when it was
     // retired. We have to remove it now, since we don't allow regions
     // we allocate to in the region sets. We'll re-add it later, when
@@ -94,6 +94,9 @@
   // want either way so no reason to check explicitly for either
   // condition.
   _retained_old_gc_alloc_region = old_gc_alloc_region(context)->release();
+  if (_retained_old_gc_alloc_region != NULL) {
+    _retained_old_gc_alloc_region->record_retained_region();
+  }
 
   if (ResizePLAB) {
     _g1h->_survivor_plab_stats.adjust_desired_plab_sz(no_of_gc_workers);
@@ -110,15 +113,16 @@
 G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
   ParGCAllocBuffer(gclab_word_size), _retired(true) { }
 
-HeapWord* G1ParGCAllocator::allocate_slow(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context) {
-  HeapWord* obj = NULL;
-  size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
+HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest,
+                                                        size_t word_sz,
+                                                        AllocationContext_t context) {
+  size_t gclab_word_size = _g1h->desired_plab_sz(dest);
   if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
-    G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose, context);
+    G1ParGCAllocBuffer* alloc_buf = alloc_buffer(dest, context);
     add_to_alloc_buffer_waste(alloc_buf->words_remaining());
     alloc_buf->retire(false /* end_of_gc */, false /* retain */);
 
-    HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size, context);
+    HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
     if (buf == NULL) {
       return NULL; // Let caller handle allocation failure.
     }
@@ -126,30 +130,33 @@
     alloc_buf->set_word_size(gclab_word_size);
     alloc_buf->set_buf(buf);
 
-    obj = alloc_buf->allocate(word_sz);
+    HeapWord* const obj = alloc_buf->allocate(word_sz);
     assert(obj != NULL, "buffer was definitely big enough...");
+    return obj;
   } else {
-    obj = _g1h->par_allocate_during_gc(purpose, word_sz, context);
+    return _g1h->par_allocate_during_gc(dest, word_sz, context);
   }
-  return obj;
 }
 
 G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) :
-            G1ParGCAllocator(g1h),
-            _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)),
-            _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)) {
-
-  _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
-  _alloc_buffers[GCAllocForTenured]  = &_tenured_alloc_buffer;
-
+  G1ParGCAllocator(g1h),
+  _surviving_alloc_buffer(g1h->desired_plab_sz(InCSetState::Young)),
+  _tenured_alloc_buffer(g1h->desired_plab_sz(InCSetState::Old)) {
+  for (uint state = 0; state < InCSetState::Num; state++) {
+    _alloc_buffers[state] = NULL;
+  }
+  _alloc_buffers[InCSetState::Young] = &_surviving_alloc_buffer;
+  _alloc_buffers[InCSetState::Old]  = &_tenured_alloc_buffer;
 }
 
 void G1DefaultParGCAllocator::retire_alloc_buffers() {
-  for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
-    size_t waste = _alloc_buffers[ap]->words_remaining();
-    add_to_alloc_buffer_waste(waste);
-    _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap),
-                                               true /* end_of_gc */,
-                                               false /* retain */);
+  for (uint state = 0; state < InCSetState::Num; state++) {
+    G1ParGCAllocBuffer* const buf = _alloc_buffers[state];
+    if (buf != NULL) {
+      add_to_alloc_buffer_waste(buf->words_remaining());
+      buf->flush_stats_and_retire(_g1h->alloc_buffer_stats(state),
+                                  true /* end_of_gc */,
+                                  false /* retain */);
+    }
   }
 }
--- a/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -27,14 +27,9 @@
 
 #include "gc_implementation/g1/g1AllocationContext.hpp"
 #include "gc_implementation/g1/g1AllocRegion.hpp"
+#include "gc_implementation/g1/g1InCSetState.hpp"
 #include "gc_implementation/shared/parGCAllocBuffer.hpp"
 
-enum GCAllocPurpose {
-  GCAllocForTenured,
-  GCAllocForSurvived,
-  GCAllocPurposeCount
-};
-
 // Base class for G1 allocators.
 class G1Allocator : public CHeapObj<mtGC> {
   friend class VMStructs;
@@ -178,20 +173,40 @@
 protected:
   G1CollectedHeap* _g1h;
 
+  // The survivor alignment in effect in bytes.
+  // == 0 : don't align survivors
+  // != 0 : align survivors to that alignment
+  // These values were chosen to favor the non-alignment case since some
+  // architectures have a special compare against zero instructions.
+  const uint _survivor_alignment_bytes;
+
   size_t _alloc_buffer_waste;
   size_t _undo_waste;
 
   void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
   void add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
 
-  HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context);
+  virtual void retire_alloc_buffers() = 0;
+  virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
 
-  virtual void retire_alloc_buffers() = 0;
-  virtual G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose, AllocationContext_t context) = 0;
+  // Calculate the survivor space object alignment in bytes. Returns that or 0 if
+  // there are no restrictions on survivor alignment.
+  static uint calc_survivor_alignment_bytes() {
+    assert(SurvivorAlignmentInBytes >= ObjectAlignmentInBytes, "sanity");
+    if (SurvivorAlignmentInBytes == ObjectAlignmentInBytes) {
+      // No need to align objects in the survivors differently, return 0
+      // which means "survivor alignment is not used".
+      return 0;
+    } else {
+      assert(SurvivorAlignmentInBytes > 0, "sanity");
+      return SurvivorAlignmentInBytes;
+    }
+  }
 
 public:
   G1ParGCAllocator(G1CollectedHeap* g1h) :
-    _g1h(g1h), _alloc_buffer_waste(0), _undo_waste(0) {
+    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()),
+    _alloc_buffer_waste(0), _undo_waste(0) {
   }
 
   static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
@@ -199,24 +214,40 @@
   size_t alloc_buffer_waste() { return _alloc_buffer_waste; }
   size_t undo_waste() {return _undo_waste; }
 
-  HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context) {
-    HeapWord* obj = NULL;
-    if (purpose == GCAllocForSurvived) {
-      obj = alloc_buffer(purpose, context)->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
+  // Allocate word_sz words in dest, either directly into the regions or by
+  // allocating a new PLAB. Returns the address of the allocated memory, NULL if
+  // not successful.
+  HeapWord* allocate_direct_or_new_plab(InCSetState dest,
+                                        size_t word_sz,
+                                        AllocationContext_t context);
+
+  // Allocate word_sz words in the PLAB of dest.  Returns the address of the
+  // allocated memory, NULL if not successful.
+  HeapWord* plab_allocate(InCSetState dest,
+                          size_t word_sz,
+                          AllocationContext_t context) {
+    G1ParGCAllocBuffer* buffer = alloc_buffer(dest, context);
+    if (_survivor_alignment_bytes == 0) {
+      return buffer->allocate(word_sz);
     } else {
-      obj = alloc_buffer(purpose, context)->allocate(word_sz);
+      return buffer->allocate_aligned(word_sz, _survivor_alignment_bytes);
     }
+  }
+
+  HeapWord* allocate(InCSetState dest, size_t word_sz,
+                     AllocationContext_t context) {
+    HeapWord* const obj = plab_allocate(dest, word_sz, context);
     if (obj != NULL) {
       return obj;
     }
-    return allocate_slow(purpose, word_sz, context);
+    return allocate_direct_or_new_plab(dest, word_sz, context);
   }
 
-  void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
-    if (alloc_buffer(purpose, context)->contains(obj)) {
-      assert(alloc_buffer(purpose, context)->contains(obj + word_sz - 1),
+  void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
+    if (alloc_buffer(dest, context)->contains(obj)) {
+      assert(alloc_buffer(dest, context)->contains(obj + word_sz - 1),
              "should contain whole object");
-      alloc_buffer(purpose, context)->undo_allocation(obj, word_sz);
+      alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
     } else {
       CollectedHeap::fill_with_object(obj, word_sz);
       add_to_undo_waste(word_sz);
@@ -227,13 +258,17 @@
 class G1DefaultParGCAllocator : public G1ParGCAllocator {
   G1ParGCAllocBuffer  _surviving_alloc_buffer;
   G1ParGCAllocBuffer  _tenured_alloc_buffer;
-  G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
+  G1ParGCAllocBuffer* _alloc_buffers[InCSetState::Num];
 
 public:
   G1DefaultParGCAllocator(G1CollectedHeap* g1h);
 
-  virtual G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose, AllocationContext_t context) {
-    return _alloc_buffers[purpose];
+  virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) {
+    assert(dest.is_valid(),
+           err_msg("Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value()));
+    assert(_alloc_buffers[dest.value()] != NULL,
+           err_msg("Allocation buffer is NULL: " CSETSTATE_FORMAT, dest.value()));
+    return _alloc_buffers[dest.value()];
   }
 
   virtual void retire_alloc_buffers() ;
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,6 +46,7 @@
 #include "gc_implementation/g1/g1ParScanThreadState.inline.hpp"
 #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "gc_implementation/g1/g1RootProcessor.hpp"
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
@@ -85,18 +86,6 @@
 // apply to TLAB allocation, which is not part of this interface: it
 // is done by clients of this interface.)
 
-// Notes on implementation of parallelism in different tasks.
-//
-// G1ParVerifyTask uses heap_region_par_iterate_chunked() for parallelism.
-// The number of GC workers is passed to heap_region_par_iterate_chunked().
-// It does use run_task() which sets _n_workers in the task.
-// G1ParTask executes g1_process_roots() ->
-// SharedHeap::process_roots() which calls eventually to
-// CardTableModRefBS::par_non_clean_card_iterate_work() which uses
-// SequentialSubTasksDone.  SharedHeap::process_roots() also
-// directly uses SubTasksDone (_process_strong_tasks field in SharedHeap).
-//
-
 // Local to this file.
 
 class RefineCardTableEntryClosure: public CardTableEntryClosure {
@@ -364,7 +353,7 @@
   HeapRegion* lists[] = {_head,   _survivor_head};
   const char* names[] = {"YOUNG", "SURVIVOR"};
 
-  for (unsigned int list = 0; list < ARRAY_SIZE(lists); ++list) {
+  for (uint list = 0; list < ARRAY_SIZE(lists); ++list) {
     gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]);
     HeapRegion *curr = lists[list];
     if (curr == NULL)
@@ -838,8 +827,8 @@
   assert_heap_not_locked_and_not_at_safepoint();
   assert(!isHumongous(word_size), "we do not allow humongous TLABs");
 
-  unsigned int dummy_gc_count_before;
-  int dummy_gclocker_retry_count = 0;
+  uint dummy_gc_count_before;
+  uint dummy_gclocker_retry_count = 0;
   return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count);
 }
 
@@ -849,8 +838,8 @@
   assert_heap_not_locked_and_not_at_safepoint();
 
   // Loop until the allocation is satisfied, or unsatisfied after GC.
-  for (int try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
-    unsigned int gc_count_before;
+  for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
+    uint gc_count_before;
 
     HeapWord* result = NULL;
     if (!isHumongous(word_size)) {
@@ -902,8 +891,8 @@
 
 HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
                                                    AllocationContext_t context,
-                                                   unsigned int *gc_count_before_ret,
-                                                   int* gclocker_retry_count_ret) {
+                                                   uint* gc_count_before_ret,
+                                                   uint* gclocker_retry_count_ret) {
   // Make sure you read the note in attempt_allocation_humongous().
 
   assert_heap_not_locked_and_not_at_safepoint();
@@ -920,7 +909,7 @@
   HeapWord* result = NULL;
   for (int try_count = 1; /* we'll return */; try_count += 1) {
     bool should_try_gc;
-    unsigned int gc_count_before;
+    uint gc_count_before;
 
     {
       MutexLockerEx x(Heap_lock);
@@ -964,7 +953,7 @@
     if (should_try_gc) {
       bool succeeded;
       result = do_collection_pause(word_size, gc_count_before, &succeeded,
-          GCCause::_g1_inc_collection_pause);
+                                   GCCause::_g1_inc_collection_pause);
       if (result != NULL) {
         assert(succeeded, "only way to get back a non-NULL result");
         return result;
@@ -1018,8 +1007,8 @@
 }
 
 HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
-                                                        unsigned int * gc_count_before_ret,
-                                                        int* gclocker_retry_count_ret) {
+                                                        uint* gc_count_before_ret,
+                                                        uint* 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
@@ -1052,7 +1041,7 @@
   HeapWord* result = NULL;
   for (int try_count = 1; /* we'll return */; try_count += 1) {
     bool should_try_gc;
-    unsigned int gc_count_before;
+    uint gc_count_before;
 
     {
       MutexLockerEx x(Heap_lock);
@@ -1090,7 +1079,7 @@
 
       bool succeeded;
       result = do_collection_pause(word_size, gc_count_before, &succeeded,
-          GCCause::_g1_humongous_allocation);
+                                   GCCause::_g1_humongous_allocation);
       if (result != NULL) {
         assert(succeeded, "only way to get back a non-NULL result");
         return result;
@@ -1297,7 +1286,6 @@
 
     // Timing
     assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
-    gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
     {
@@ -1855,7 +1843,6 @@
   _is_alive_closure_stw(this),
   _ref_processor_cm(NULL),
   _ref_processor_stw(NULL),
-  _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   _bot_shared(NULL),
   _evac_failure_scan_stack(NULL),
   _mark_in_progress(false),
@@ -1878,6 +1865,7 @@
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
   _concurrent_cycle_started(false),
+  _heap_summary_sent(false),
   _in_cset_fast_test(),
   _dirty_cards_region_list(NULL),
   _worker_cset_start_region(NULL),
@@ -1888,9 +1876,6 @@
   _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) G1OldTracer()) {
 
   _g1h = this;
-  if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
-    vm_exit_during_initialization("Failed necessary allocation.");
-  }
 
   _allocator = G1Allocator::create_allocator(_g1h);
   _humongous_object_threshold_in_words = HeapRegion::GrainWords / 2;
@@ -1902,7 +1887,7 @@
   assert(n_rem_sets > 0, "Invariant.");
 
   _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC);
-  _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues, mtGC);
+  _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(uint, n_queues, mtGC);
   _evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC);
 
   for (int i = 0; i < n_queues; i++) {
@@ -2299,11 +2284,11 @@
   hot_card_cache->drain(worker_i, g1_rem_set(), into_cset_dcq);
 
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-  int n_completed_buffers = 0;
+  size_t n_completed_buffers = 0;
   while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) {
     n_completed_buffers++;
   }
-  g1_policy()->phase_times()->record_update_rs_processed_buffers(worker_i, n_completed_buffers);
+  g1_policy()->phase_times()->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, n_completed_buffers);
   dcqs.clear_n_completed_buffers();
   assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!");
 }
@@ -2448,13 +2433,24 @@
     _gc_timer_cm->register_gc_end();
     _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions());
 
+    // Clear state variables to prepare for the next concurrent cycle.
     _concurrent_cycle_started = false;
+    _heap_summary_sent = false;
   }
 }
 
 void G1CollectedHeap::trace_heap_after_concurrent_cycle() {
   if (_concurrent_cycle_started) {
-    trace_heap_after_gc(_gc_tracer_cm);
+    // This function can be called when:
+    //  the cleanup pause is run
+    //  the concurrent cycle is aborted before the cleanup pause.
+    //  the concurrent cycle is aborted after the cleanup pause,
+    //   but before the concurrent cycle end has been registered.
+    // Make sure that we only send the heap information once.
+    if (!_heap_summary_sent) {
+      trace_heap_after_gc(_gc_tracer_cm);
+      _heap_summary_sent = true;
+    }
   }
 }
 
@@ -2477,9 +2473,9 @@
 void G1CollectedHeap::collect(GCCause::Cause cause) {
   assert_heap_not_locked();
 
-  unsigned int gc_count_before;
-  unsigned int old_marking_count_before;
-  unsigned int full_gc_count_before;
+  uint gc_count_before;
+  uint old_marking_count_before;
+  uint full_gc_count_before;
   bool retry_gc;
 
   do {
@@ -3292,11 +3288,12 @@
     G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo);
     G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl);
 
-    process_all_roots(true,            // activate StrongRootsScope
-                      SO_AllCodeCache, // roots scanning options
-                      &rootsCl,
-                      &cldCl,
-                      &blobsCl);
+    {
+      G1RootProcessor root_processor(this);
+      root_processor.process_all_roots(&rootsCl,
+                                       &cldCl,
+                                       &blobsCl);
+    }
 
     bool failures = rootsCl.failures() || codeRootsCl.failures();
 
@@ -3616,7 +3613,7 @@
 }
 
 HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
-                                               unsigned int gc_count_before,
+                                               uint gc_count_before,
                                                bool* succeeded,
                                                GCCause::Cause gc_cause) {
   assert_heap_not_locked_and_not_at_safepoint();
@@ -3721,7 +3718,7 @@
                                                                   cl.candidate_humongous());
   _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
 
-  if (_has_humongous_reclaim_candidates) {
+  if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
     clear_humongous_is_live_table();
   }
 }
@@ -3901,10 +3898,10 @@
 
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
-    int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+    uint active_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
                                 workers()->active_workers() : 1);
     double pause_start_sec = os::elapsedTime();
-    g1_policy()->phase_times()->note_gc_start(active_workers);
+    g1_policy()->phase_times()->note_gc_start(active_workers, mark_in_progress());
     log_gc_header();
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
@@ -4014,6 +4011,8 @@
 
         register_humongous_regions_with_in_cset_fast_test();
 
+        assert(check_cset_fast_test(), "Inconsistency in the InCSetState table.");
+
         _cm->note_start_of_gc();
         // We should not verify the per-thread SATB buffers given that
         // we have not filtered them yet (we'll do so during the
@@ -4243,29 +4242,6 @@
   return true;
 }
 
-size_t G1CollectedHeap::desired_plab_sz(GCAllocPurpose purpose)
-{
-  size_t gclab_word_size;
-  switch (purpose) {
-    case GCAllocForSurvived:
-      gclab_word_size = _survivor_plab_stats.desired_plab_sz();
-      break;
-    case GCAllocForTenured:
-      gclab_word_size = _old_plab_stats.desired_plab_sz();
-      break;
-    default:
-      assert(false, "unknown GCAllocPurpose");
-      gclab_word_size = _old_plab_stats.desired_plab_sz();
-      break;
-  }
-
-  // Prevent humongous PLAB sizes for two reasons:
-  // * PLABs are allocated using a similar paths as oops, but should
-  //   never be in a humongous region
-  // * Allowing humongous PLABs needlessly churns the region free lists
-  return MIN2(_humongous_object_threshold_in_words, gclab_word_size);
-}
-
 void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) {
   _drain_in_progress = false;
   set_evac_failure_closure(cl);
@@ -4405,35 +4381,6 @@
   }
 }
 
-HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose,
-                                                  size_t word_size,
-                                                  AllocationContext_t context) {
-  if (purpose == GCAllocForSurvived) {
-    HeapWord* result = survivor_attempt_allocation(word_size, context);
-    if (result != NULL) {
-      return result;
-    } else {
-      // Let's try to allocate in the old gen in case we can fit the
-      // object there.
-      return old_attempt_allocation(word_size, context);
-    }
-  } else {
-    assert(purpose ==  GCAllocForTenured, "sanity");
-    HeapWord* result = old_attempt_allocation(word_size, context);
-    if (result != NULL) {
-      return result;
-    } else {
-      // Let's try to allocate in the survivors in case we can fit the
-      // object there.
-      return survivor_attempt_allocation(word_size, context);
-    }
-  }
-
-  ShouldNotReachHere();
-  // Trying to keep some compilers happy.
-  return NULL;
-}
-
 void G1ParCopyHelper::mark_object(oop obj) {
   assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet");
 
@@ -4476,14 +4423,14 @@
 
   assert(_worker_id == _par_scan_state->queue_num(), "sanity");
 
-  G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj);
-
-  if (state == G1CollectedHeap::InCSet) {
+  const InCSetState state = _g1->in_cset_state(obj);
+  if (state.is_in_cset()) {
     oop forwardee;
-    if (obj->is_forwarded()) {
-      forwardee = obj->forwardee();
+    markOop m = obj->mark();
+    if (m->is_marked()) {
+      forwardee = (oop) m->decode_pointer();
     } else {
-      forwardee = _par_scan_state->copy_to_survivor_space(obj);
+      forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
     }
     assert(forwardee != NULL, "forwardee should not be NULL");
     oopDesc::encode_store_heap_oop(p, forwardee);
@@ -4497,7 +4444,7 @@
       do_klass_barrier(p, forwardee);
     }
   } else {
-    if (state == G1CollectedHeap::IsHumongous) {
+    if (state.is_humongous()) {
       _g1->set_humongous_is_live(obj);
     }
     // The object is not in collection set. If we're a root scanning
@@ -4582,60 +4529,11 @@
   }
 };
 
-class G1CodeBlobClosure : public CodeBlobClosure {
-  class HeapRegionGatheringOopClosure : public OopClosure {
-    G1CollectedHeap* _g1h;
-    OopClosure* _work;
-    nmethod* _nm;
-
-    template <typename T>
-    void do_oop_work(T* p) {
-      _work->do_oop(p);
-      T oop_or_narrowoop = oopDesc::load_heap_oop(p);
-      if (!oopDesc::is_null(oop_or_narrowoop)) {
-        oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
-        HeapRegion* hr = _g1h->heap_region_containing_raw(o);
-        assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
-        hr->add_strong_code_root(_nm);
-      }
-    }
-
-  public:
-    HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
-
-    void do_oop(oop* o) {
-      do_oop_work(o);
-    }
-
-    void do_oop(narrowOop* o) {
-      do_oop_work(o);
-    }
-
-    void set_nm(nmethod* nm) {
-      _nm = nm;
-    }
-  };
-
-  HeapRegionGatheringOopClosure _oc;
-public:
-  G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
-
-  void do_code_blob(CodeBlob* cb) {
-    nmethod* nm = cb->as_nmethod_or_null();
-    if (nm != NULL) {
-      if (!nm->test_set_oops_do_mark()) {
-        _oc.set_nm(nm);
-        nm->oops_do(&_oc);
-        nm->fix_oop_relocations();
-      }
-    }
-  }
-};
-
 class G1ParTask : public AbstractGangTask {
 protected:
   G1CollectedHeap*       _g1h;
   RefToScanQueueSet      *_queues;
+  G1RootProcessor*       _root_processor;
   ParallelTaskTerminator _terminator;
   uint _n_workers;
 
@@ -4643,10 +4541,11 @@
   Mutex* stats_lock() { return &_stats_lock; }
 
 public:
-  G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues)
+  G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor)
     : AbstractGangTask("G1 collection"),
       _g1h(g1h),
       _queues(task_queues),
+      _root_processor(root_processor),
       _terminator(0, _queues),
       _stats_lock(Mutex::leaf, "parallel G1 stats lock", true)
   {}
@@ -4660,13 +4559,7 @@
   ParallelTaskTerminator* terminator() { return &_terminator; }
 
   virtual void set_for_termination(int active_workers) {
-    // This task calls set_n_termination() in par_non_clean_card_iterate_work()
-    // in the young space (_par_seq_tasks) in the G1 heap
-    // for SequentialSubTasksDone.
-    // This task also uses SubTasksDone in SharedHeap and G1CollectedHeap
-    // both of which need setting by set_n_termination().
-    _g1h->SharedHeap::set_n_termination(active_workers);
-    _g1h->set_n_termination(active_workers);
+    _root_processor->set_num_workers(active_workers);
     terminator()->reset_for_reuse(active_workers);
     _n_workers = active_workers;
   }
@@ -4703,8 +4596,7 @@
   void work(uint worker_id) {
     if (worker_id >= _n_workers) return;  // no work needed this round
 
-    double start_time_ms = os::elapsedTime() * 1000.0;
-    _g1h->g1_policy()->phase_times()->record_gc_worker_start_time(worker_id, start_time_ms);
+    _g1h->g1_policy()->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerStart, worker_id, os::elapsedTime());
 
     {
       ResourceMark rm;
@@ -4736,24 +4628,21 @@
                                                                                     false, // Process all klasses.
                                                                                     true); // Need to claim CLDs.
 
-      G1CodeBlobClosure scan_only_code_cl(&scan_only_root_cl);
-      G1CodeBlobClosure scan_mark_code_cl(&scan_mark_root_cl);
-      // IM Weak code roots are handled later.
-
       OopClosure* strong_root_cl;
       OopClosure* weak_root_cl;
       CLDClosure* strong_cld_cl;
       CLDClosure* weak_cld_cl;
-      CodeBlobClosure* strong_code_cl;
+
+      bool trace_metadata = false;
 
       if (_g1h->g1_policy()->during_initial_mark_pause()) {
         // We also need to mark copied objects.
         strong_root_cl = &scan_mark_root_cl;
         strong_cld_cl  = &scan_mark_cld_cl;
-        strong_code_cl = &scan_mark_code_cl;
         if (ClassUnloadingWithConcurrentMark) {
           weak_root_cl = &scan_mark_weak_root_cl;
           weak_cld_cl  = &scan_mark_weak_cld_cl;
+          trace_metadata = true;
         } else {
           weak_root_cl = &scan_mark_root_cl;
           weak_cld_cl  = &scan_mark_cld_cl;
@@ -4763,31 +4652,32 @@
         weak_root_cl   = &scan_only_root_cl;
         strong_cld_cl  = &scan_only_cld_cl;
         weak_cld_cl    = &scan_only_cld_cl;
-        strong_code_cl = &scan_only_code_cl;
       }
 
-
-      G1ParPushHeapRSClosure  push_heap_rs_cl(_g1h, &pss);
-
       pss.start_strong_roots();
-      _g1h->g1_process_roots(strong_root_cl,
-                             weak_root_cl,
-                             &push_heap_rs_cl,
-                             strong_cld_cl,
-                             weak_cld_cl,
-                             strong_code_cl,
-                             worker_id);
-
+
+      _root_processor->evacuate_roots(strong_root_cl,
+                                      weak_root_cl,
+                                      strong_cld_cl,
+                                      weak_cld_cl,
+                                      trace_metadata,
+                                      worker_id);
+
+      G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
+      _root_processor->scan_remembered_sets(&push_heap_rs_cl,
+                                            weak_root_cl,
+                                            worker_id);
       pss.end_strong_roots();
 
       {
         double start = os::elapsedTime();
         G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
         evac.do_void();
-        double elapsed_ms = (os::elapsedTime()-start)*1000.0;
-        double term_ms = pss.term_time()*1000.0;
-        _g1h->g1_policy()->phase_times()->add_obj_copy_time(worker_id, elapsed_ms-term_ms);
-        _g1h->g1_policy()->phase_times()->record_termination(worker_id, term_ms, pss.term_attempts());
+        double elapsed_sec = os::elapsedTime() - start;
+        double term_sec = pss.term_time();
+        _g1h->g1_policy()->phase_times()->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_id, elapsed_sec - term_sec);
+        _g1h->g1_policy()->phase_times()->record_time_secs(G1GCPhaseTimes::Termination, worker_id, term_sec);
+        _g1h->g1_policy()->phase_times()->record_thread_work_item(G1GCPhaseTimes::Termination, worker_id, pss.term_attempts());
       }
       _g1h->g1_policy()->record_thread_age_table(pss.age_table());
       _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
@@ -4803,100 +4693,10 @@
       // destructors are executed here and are included as part of the
       // "GC Worker Time".
     }
-
-    double end_time_ms = os::elapsedTime() * 1000.0;
-    _g1h->g1_policy()->phase_times()->record_gc_worker_end_time(worker_id, end_time_ms);
+    _g1h->g1_policy()->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerEnd, worker_id, os::elapsedTime());
   }
 };
 
-// *** Common G1 Evacuation Stuff
-
-// This method is run in a GC worker.
-
-void
-G1CollectedHeap::
-g1_process_roots(OopClosure* scan_non_heap_roots,
-                 OopClosure* scan_non_heap_weak_roots,
-                 OopsInHeapRegionClosure* scan_rs,
-                 CLDClosure* scan_strong_clds,
-                 CLDClosure* scan_weak_clds,
-                 CodeBlobClosure* scan_strong_code,
-                 uint worker_i) {
-
-  // First scan the shared roots.
-  double ext_roots_start = os::elapsedTime();
-  double closure_app_time_sec = 0.0;
-
-  bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
-  bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark;
-
-  BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
-  BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
-
-  process_roots(false, // no scoping; this is parallel code
-                SharedHeap::SO_None,
-                &buf_scan_non_heap_roots,
-                &buf_scan_non_heap_weak_roots,
-                scan_strong_clds,
-                // Unloading Initial Marks handle the weak CLDs separately.
-                (trace_metadata ? NULL : scan_weak_clds),
-                scan_strong_code);
-
-  // Now the CM ref_processor roots.
-  if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
-    // We need to treat the discovered reference lists of the
-    // concurrent mark ref processor as roots and keep entries
-    // (which are added by the marking threads) on them live
-    // until they can be processed at the end of marking.
-    ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
-  }
-
-  if (trace_metadata) {
-    // Barrier to make sure all workers passed
-    // the strong CLD and strong nmethods phases.
-    active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads());
-
-    // Now take the complement of the strong CLDs.
-    ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
-  }
-
-  // Finish up any enqueued closure apps (attributed as object copy time).
-  buf_scan_non_heap_roots.done();
-  buf_scan_non_heap_weak_roots.done();
-
-  double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
-      + buf_scan_non_heap_weak_roots.closure_app_seconds();
-
-  g1_policy()->phase_times()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
-
-  double ext_root_time_ms =
-    ((os::elapsedTime() - ext_roots_start) - obj_copy_time_sec) * 1000.0;
-
-  g1_policy()->phase_times()->record_ext_root_scan_time(worker_i, ext_root_time_ms);
-
-  // During conc marking we have to filter the per-thread SATB buffers
-  // to make sure we remove any oops into the CSet (which will show up
-  // as implicitly live).
-  double satb_filtering_ms = 0.0;
-  if (!_process_strong_tasks->is_task_claimed(G1H_PS_filter_satb_buffers)) {
-    if (mark_in_progress()) {
-      double satb_filter_start = os::elapsedTime();
-
-      JavaThread::satb_mark_queue_set().filter_thread_buffers();
-
-      satb_filtering_ms = (os::elapsedTime() - satb_filter_start) * 1000.0;
-    }
-  }
-  g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
-
-  // Now scan the complement of the collection set.
-  G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
-
-  g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
-
-  _process_strong_tasks->all_tasks_completed();
-}
-
 class G1StringSymbolTableUnlinkTask : public AbstractGangTask {
 private:
   BoolObjectClosure* _is_alive;
@@ -5310,7 +5110,8 @@
   G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { }
 
   virtual void work(uint worker_id) {
-    double start_time = os::elapsedTime();
+    G1GCPhaseTimes* phase_times = G1CollectedHeap::heap()->g1_policy()->phase_times();
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
 
     RedirtyLoggedCardTableEntryClosure cl;
     if (G1CollectedHeap::heap()->use_parallel_gc_threads()) {
@@ -5319,9 +5120,7 @@
       _queue->apply_closure_to_all_completed_buffers(&cl);
     }
 
-    G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times();
-    timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0);
-    timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed());
+    phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_processed());
   }
 };
 
@@ -5382,17 +5181,17 @@
     oop obj = *p;
     assert(obj != NULL, "the caller should have filtered out NULL values");
 
-    G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj);
-    if (cset_state == G1CollectedHeap::InNeither) {
+    const InCSetState cset_state = _g1->in_cset_state(obj);
+    if (!cset_state.is_in_cset_or_humongous()) {
       return;
     }
-    if (cset_state == G1CollectedHeap::InCSet) {
+    if (cset_state.is_in_cset()) {
       assert( obj->is_forwarded(), "invariant" );
       *p = obj->forwardee();
     } else {
       assert(!obj->is_forwarded(), "invariant" );
-      assert(cset_state == G1CollectedHeap::IsHumongous,
-             err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state));
+      assert(cset_state.is_humongous(),
+             err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state.value()));
       _g1->set_humongous_is_live(obj);
     }
   }
@@ -5885,7 +5684,6 @@
     n_workers = 1;
   }
 
-  G1ParTask g1_par_task(this, _task_queues);
 
   init_for_evac_failure(NULL);
 
@@ -5896,7 +5694,8 @@
   double end_par_time_sec;
 
   {
-    StrongRootsScope srs(this);
+    G1RootProcessor root_processor(this);
+    G1ParTask g1_par_task(this, _task_queues, &root_processor);
     // InitialMark needs claim bits to keep track of the marked-through CLDs.
     if (g1_policy()->during_initial_mark_pause()) {
       ClassLoaderDataGraph::clear_claimed_marks();
@@ -5917,18 +5716,20 @@
     end_par_time_sec = os::elapsedTime();
 
     // Closing the inner scope will execute the destructor
-    // for the StrongRootsScope object. We record the current
+    // for the G1RootProcessor object. We record the current
     // elapsed time before closing the scope so that time
-    // taken for the SRS destructor is NOT included in the
+    // taken for the destructor is NOT included in the
     // reported parallel time.
   }
 
+  G1GCPhaseTimes* phase_times = g1_policy()->phase_times();
+
   double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
-  g1_policy()->phase_times()->record_par_time(par_time_ms);
+  phase_times->record_par_time(par_time_ms);
 
   double code_root_fixup_time_ms =
         (os::elapsedTime() - end_par_time_sec) * 1000.0;
-  g1_policy()->phase_times()->record_code_root_fixup_time(code_root_fixup_time_ms);
+  phase_times->record_code_root_fixup_time(code_root_fixup_time_ms);
 
   set_par_threads(0);
 
@@ -5939,14 +5740,15 @@
   // not copied during the pause.
   process_discovered_references(n_workers);
 
-  // Weak root processing.
-  {
+  if (G1StringDedup::is_enabled()) {
+    double fixup_start = os::elapsedTime();
+
     G1STWIsAliveClosure is_alive(this);
     G1KeepAliveClosure keep_alive(this);
-    JNIHandles::weak_oops_do(&is_alive, &keep_alive);
-    if (G1StringDedup::is_enabled()) {
-      G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive);
-    }
+    G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive, true, phase_times);
+
+    double fixup_time_ms = (os::elapsedTime() - fixup_start) * 1000.0;
+    phase_times->record_string_dedup_fixup_time(fixup_time_ms);
   }
 
   _allocator->release_gc_alloc_regions(n_workers, evacuation_info);
@@ -6214,6 +6016,70 @@
   heap_region_iterate(&cl);
   guarantee(!cl.failures(), "bitmap verification");
 }
+
+class G1CheckCSetFastTableClosure : public HeapRegionClosure {
+ private:
+  bool _failures;
+ public:
+  G1CheckCSetFastTableClosure() : HeapRegionClosure(), _failures(false) { }
+
+  virtual bool doHeapRegion(HeapRegion* hr) {
+    uint i = hr->hrm_index();
+    InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i);
+    if (hr->isHumongous()) {
+      if (hr->in_collection_set()) {
+        gclog_or_tty->print_cr("\n## humongous region %u in CSet", i);
+        _failures = true;
+        return true;
+      }
+      if (cset_state.is_in_cset()) {
+        gclog_or_tty->print_cr("\n## inconsistent cset state %d for humongous region %u", cset_state.value(), i);
+        _failures = true;
+        return true;
+      }
+      if (hr->continuesHumongous() && cset_state.is_humongous()) {
+        gclog_or_tty->print_cr("\n## inconsistent cset state %d for continues humongous region %u", cset_state.value(), i);
+        _failures = true;
+        return true;
+      }
+    } else {
+      if (cset_state.is_humongous()) {
+        gclog_or_tty->print_cr("\n## inconsistent cset state %d for non-humongous region %u", cset_state.value(), i);
+        _failures = true;
+        return true;
+      }
+      if (hr->in_collection_set() != cset_state.is_in_cset()) {
+        gclog_or_tty->print_cr("\n## in CSet %d / cset state %d inconsistency for region %u",
+                               hr->in_collection_set(), cset_state.value(), i);
+       _failures = true;
+       return true;
+      }
+      if (cset_state.is_in_cset()) {
+        if (hr->is_young() != (cset_state.is_young())) {
+          gclog_or_tty->print_cr("\n## is_young %d / cset state %d inconsistency for region %u",
+                                 hr->is_young(), cset_state.value(), i);
+          _failures = true;
+          return true;
+        }
+        if (hr->is_old() != (cset_state.is_old())) {
+          gclog_or_tty->print_cr("\n## is_old %d / cset state %d inconsistency for region %u",
+                                 hr->is_old(), cset_state.value(), i);
+          _failures = true;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  bool failures() const { return _failures; }
+};
+
+bool G1CollectedHeap::check_cset_fast_test() {
+  G1CheckCSetFastTableClosure cl;
+  _hrm.iterate(&cl);
+  return !cl.failures();
+}
 #endif // PRODUCT
 
 void G1CollectedHeap::cleanUpCardTable() {
@@ -6421,9 +6287,10 @@
         g1h->humongous_region_is_always_live(region_idx)) {
 
       if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
-        gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
+        gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
                                r->isHumongous(),
                                region_idx,
+                               obj->size()*HeapWordSize,
                                r->rem_set()->occupied(),
                                r->rem_set()->strong_code_roots_list_length(),
                                next_bitmap->isMarked(r->bottom()),
@@ -6440,8 +6307,9 @@
                       r->bottom()));
 
     if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
-      gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
+      gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other ",
                              r->isHumongous(),
+                             obj->size()*HeapWordSize,
                              r->bottom(),
                              region_idx,
                              r->region_num(),
@@ -6480,7 +6348,8 @@
 void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
   assert_at_safepoint(true);
 
-  if (!G1ReclaimDeadHumongousObjectsAtYoungGC || !_has_humongous_reclaim_candidates) {
+  if (!G1ReclaimDeadHumongousObjectsAtYoungGC ||
+      (!_has_humongous_reclaim_candidates && !G1TraceReclaimDeadHumongousObjectsAtYoungGC)) {
     g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0);
     return;
   }
@@ -6793,20 +6662,20 @@
 
 HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size,
                                                  uint count,
-                                                 GCAllocPurpose ap) {
+                                                 InCSetState dest) {
   assert(FreeList_lock->owned_by_self(), "pre-condition");
 
-  if (count < g1_policy()->max_regions(ap)) {
-    bool survivor = (ap == GCAllocForSurvived);
+  if (count < g1_policy()->max_regions(dest)) {
+    const bool is_survivor = (dest.is_young());
     HeapRegion* new_alloc_region = new_region(word_size,
-                                              !survivor,
+                                              !is_survivor,
                                               true /* do_expand */);
     if (new_alloc_region != NULL) {
       // We really only need to do this for old regions given that we
       // should never scan survivors. But it doesn't hurt to do it
       // for survivors too.
-      new_alloc_region->record_top_and_timestamp();
-      if (survivor) {
+      new_alloc_region->record_timestamp();
+      if (is_survivor) {
         new_alloc_region->set_survivor();
         _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor);
         check_bitmaps("Survivor Region Allocation", new_alloc_region);
@@ -6818,8 +6687,6 @@
       bool during_im = g1_policy()->during_initial_mark_pause();
       new_alloc_region->note_start_of_copying(during_im);
       return new_alloc_region;
-    } else {
-      g1_policy()->note_alloc_region_limit_reached(ap);
     }
   }
   return NULL;
@@ -6827,11 +6694,11 @@
 
 void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region,
                                              size_t allocated_bytes,
-                                             GCAllocPurpose ap) {
+                                             InCSetState dest) {
   bool during_im = g1_policy()->during_initial_mark_pause();
   alloc_region->note_end_of_copying(during_im);
   g1_policy()->record_bytes_copied_during_gc(allocated_bytes);
-  if (ap == GCAllocForSurvived) {
+  if (dest.is_young()) {
     young_list()->add_survivor_region(alloc_region);
   } else {
     _old_set.add(alloc_region);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
   /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 #include "gc_implementation/g1/g1AllocRegion.hpp"
 #include "gc_implementation/g1/g1BiasedArray.hpp"
 #include "gc_implementation/g1/g1HRPrinter.hpp"
+#include "gc_implementation/g1/g1InCSetState.hpp"
 #include "gc_implementation/g1/g1MonitoringSupport.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
@@ -212,6 +213,9 @@
   // Other related classes.
   friend class G1MarkSweep;
 
+  // Testing classes.
+  friend class G1CheckCSetFastTableClosure;
+
 private:
   // The one and only G1CollectedHeap, so static functions can find it.
   static G1CollectedHeap* _g1h;
@@ -339,13 +343,14 @@
 
   // Keeps track of how many "old marking cycles" (i.e., Full GCs or
   // concurrent cycles) we have started.
-  volatile unsigned int _old_marking_cycles_started;
+  volatile uint _old_marking_cycles_started;
 
   // Keeps track of how many "old marking cycles" (i.e., Full GCs or
   // concurrent cycles) we have completed.
-  volatile unsigned int _old_marking_cycles_completed;
+  volatile uint _old_marking_cycles_completed;
 
   bool _concurrent_cycle_started;
+  bool _heap_summary_sent;
 
   // This is a non-product method that is helpful for testing. It is
   // called at the end of a GC and artificially expands the heap by
@@ -510,22 +515,22 @@
   // 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,
-                                      int* gclocker_retry_count_ret);
+                                      uint* gc_count_before_ret,
+                                      uint* 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,
                                     AllocationContext_t context,
-                                    unsigned int* gc_count_before_ret,
-                                    int* gclocker_retry_count_ret);
+                                    uint* gc_count_before_ret,
+                                    uint* 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,
-                                         int* gclocker_retry_count_ret);
+                                         uint* gc_count_before_ret,
+                                         uint* 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
@@ -545,15 +550,9 @@
   // allocation region, either by picking one or expanding the
   // heap, and then allocate a block of the given size. The block
   // may not be a humongous - it must fit into a single heap region.
-  HeapWord* par_allocate_during_gc(GCAllocPurpose purpose,
-                                   size_t word_size,
-                                   AllocationContext_t context);
-
-  HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose,
-                                    HeapRegion*    alloc_region,
-                                    bool           par,
-                                    size_t         word_size);
-
+  inline HeapWord* par_allocate_during_gc(InCSetState dest,
+                                          size_t word_size,
+                                          AllocationContext_t context);
   // Ensure that no further allocations can happen in "r", bearing in mind
   // that parallel threads might be attempting allocations.
   void par_allocate_remaining_space(HeapRegion* r);
@@ -575,9 +574,9 @@
 
   // For GC alloc regions.
   HeapRegion* new_gc_alloc_region(size_t word_size, uint count,
-                                  GCAllocPurpose ap);
+                                  InCSetState dest);
   void retire_gc_alloc_region(HeapRegion* alloc_region,
-                              size_t allocated_bytes, GCAllocPurpose ap);
+                              size_t allocated_bytes, InCSetState dest);
 
   // - if explicit_gc is true, the GC is for a System.gc() or a heap
   //   inspection request and should collect the entire heap
@@ -638,26 +637,11 @@
   // (Rounds up to a HeapRegion boundary.)
   bool expand(size_t expand_bytes);
 
-  // Returns the PLAB statistics given a purpose.
-  PLABStats* stats_for_purpose(GCAllocPurpose purpose) {
-    PLABStats* stats = NULL;
+  // Returns the PLAB statistics for a given destination.
+  inline PLABStats* alloc_buffer_stats(InCSetState dest);
 
-    switch (purpose) {
-    case GCAllocForSurvived:
-      stats = &_survivor_plab_stats;
-      break;
-    case GCAllocForTenured:
-      stats = &_old_plab_stats;
-      break;
-    default:
-      assert(false, "unrecognized GCAllocPurpose");
-    }
-
-    return stats;
-  }
-
-  // Determines PLAB size for a particular allocation purpose.
-  size_t desired_plab_sz(GCAllocPurpose purpose);
+  // Determines PLAB size for a given destination.
+  inline size_t desired_plab_sz(InCSetState dest);
 
   inline AllocationContextStats& allocation_context_stats();
 
@@ -681,8 +665,11 @@
   void register_humongous_regions_with_in_cset_fast_test();
   // We register a region with the fast "in collection set" test. We
   // simply set to true the array slot corresponding to this region.
-  void register_region_with_in_cset_fast_test(HeapRegion* r) {
-    _in_cset_fast_test.set_in_cset(r->hrm_index());
+  void register_young_region_with_in_cset_fast_test(HeapRegion* r) {
+    _in_cset_fast_test.set_in_young(r->hrm_index());
+  }
+  void register_old_region_with_in_cset_fast_test(HeapRegion* r) {
+    _in_cset_fast_test.set_in_old(r->hrm_index());
   }
 
   // This is a fast test on whether a reference points into the
@@ -714,7 +701,7 @@
   // +ExplicitGCInvokesConcurrent).
   void increment_old_marking_cycles_completed(bool concurrent);
 
-  unsigned int old_marking_cycles_completed() {
+  uint old_marking_cycles_completed() {
     return _old_marking_cycles_completed;
   }
 
@@ -773,7 +760,7 @@
   // methods that call do_collection_pause() release the Heap_lock
   // before the call, so it's easy to read gc_count_before just before.
   HeapWord* do_collection_pause(size_t         word_size,
-                                unsigned int   gc_count_before,
+                                uint           gc_count_before,
                                 bool*          succeeded,
                                 GCCause::Cause gc_cause);
 
@@ -812,22 +799,6 @@
   // statistics or updating free lists.
   void abandon_collection_set(HeapRegion* cs_head);
 
-  // Applies "scan_non_heap_roots" to roots outside the heap,
-  // "scan_rs" to roots inside the heap (having done "set_region" to
-  // indicate the region in which the root resides),
-  // and does "scan_metadata" If "scan_rs" is
-  // NULL, then this step is skipped.  The "worker_i"
-  // param is for use with parallel roots processing, and should be
-  // the "i" of the calling parallel worker thread's work(i) function.
-  // In the sequential case this param will be ignored.
-  void g1_process_roots(OopClosure* scan_non_heap_roots,
-                        OopClosure* scan_non_heap_weak_roots,
-                        OopsInHeapRegionClosure* scan_rs,
-                        CLDClosure* scan_strong_clds,
-                        CLDClosure* scan_weak_clds,
-                        CodeBlobClosure* scan_strong_code,
-                        uint worker_i);
-
   // The concurrent marker (and the thread it runs in.)
   ConcurrentMark* _cm;
   ConcurrentMarkThread* _cmThread;
@@ -1012,23 +983,12 @@
   // The heap region entry for a given worker is valid iff
   // the associated time stamp value matches the current value
   // of G1CollectedHeap::_gc_time_stamp.
-  unsigned int* _worker_cset_start_region_time_stamp;
-
-  enum G1H_process_roots_tasks {
-    G1H_PS_filter_satb_buffers,
-    G1H_PS_refProcessor_oops_do,
-    // Leave this one last.
-    G1H_PS_NumElements
-  };
-
-  SubTasksDone* _process_strong_tasks;
+  uint* _worker_cset_start_region_time_stamp;
 
   volatile bool _free_regions_coming;
 
 public:
 
-  SubTasksDone* process_strong_tasks() { return _process_strong_tasks; }
-
   void set_refine_cte_cl_concurrency(bool concurrent);
 
   RefToScanQueue *task_queue(int i) const;
@@ -1061,21 +1021,11 @@
   // Initialize weak reference processing.
   virtual void ref_processing_init();
 
-  void set_par_threads(uint t) {
-    SharedHeap::set_par_threads(t);
-    // Done in SharedHeap but oddly there are
-    // two _process_strong_tasks's in a G1CollectedHeap
-    // so do it here too.
-    _process_strong_tasks->set_n_threads(t);
-  }
-
+  // Explicitly import set_par_threads into this scope
+  using SharedHeap::set_par_threads;
   // Set _n_par_threads according to a policy TBD.
   void set_par_threads();
 
-  void set_n_termination(int t) {
-    _process_strong_tasks->set_n_threads(t);
-  }
-
   virtual CollectedHeap::Name kind() const {
     return CollectedHeap::G1CollectedHeap;
   }
@@ -1182,6 +1132,9 @@
   // appropriate error messages and crash.
   void check_bitmaps(const char* caller) PRODUCT_RETURN;
 
+  // Do sanity check on the contents of the in-cset fast test table.
+  bool check_cset_fast_test() PRODUCT_RETURN_( return true; );
+
   // verify_region_sets() performs verification over the region
   // lists. It will be compiled in the product code to be used when
   // necessary (i.e., during heap verification).
@@ -1277,53 +1230,15 @@
 
   inline bool is_in_cset_or_humongous(const oop obj);
 
-  enum in_cset_state_t {
-   InNeither,           // neither in collection set nor humongous
-   InCSet,              // region is in collection set only
-   IsHumongous          // region is a humongous start region
-  };
  private:
-  // Instances of this class are used for quick tests on whether a reference points
-  // into the collection set or is a humongous object (points into a humongous
-  // object).
-  // Each of the array's elements denotes whether the corresponding region is in
-  // the collection set or a humongous region.
-  // We use this to quickly reclaim humongous objects: by making a humongous region
-  // succeed this test, we sort-of add it to the collection set. During the reference
-  // iteration closures, when we see a humongous region, we simply mark it as
-  // referenced, i.e. live.
-  class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray<char> {
-   protected:
-    char default_value() const { return G1CollectedHeap::InNeither; }
-   public:
-    void set_humongous(uintptr_t index) {
-      assert(get_by_index(index) != InCSet, "Should not overwrite InCSet values");
-      set_by_index(index, G1CollectedHeap::IsHumongous);
-    }
-
-    void clear_humongous(uintptr_t index) {
-      set_by_index(index, G1CollectedHeap::InNeither);
-    }
-
-    void set_in_cset(uintptr_t index) {
-      assert(get_by_index(index) != G1CollectedHeap::IsHumongous, "Should not overwrite IsHumongous value");
-      set_by_index(index, G1CollectedHeap::InCSet);
-    }
-
-    bool is_in_cset_or_humongous(HeapWord* addr) const { return get_by_address(addr) != G1CollectedHeap::InNeither; }
-    bool is_in_cset(HeapWord* addr) const { return get_by_address(addr) == G1CollectedHeap::InCSet; }
-    G1CollectedHeap::in_cset_state_t at(HeapWord* addr) const { return (G1CollectedHeap::in_cset_state_t)get_by_address(addr); }
-    void clear() { G1BiasedMappedArray<char>::clear(); }
-  };
-
   // This array is used for a quick test on whether a reference points into
   // the collection set or not. Each of the array's elements denotes whether the
   // corresponding region is in the collection set or not.
-  G1FastCSetBiasedMappedArray _in_cset_fast_test;
+  G1InCSetStateFastTestBiasedMappedArray _in_cset_fast_test;
 
  public:
 
-  inline in_cset_state_t in_cset_state(const oop obj);
+  inline InCSetState in_cset_state(const oop obj);
 
   // Return "TRUE" iff the given object address is in the reserved
   // region of g1.
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,41 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
+PLABStats* G1CollectedHeap::alloc_buffer_stats(InCSetState dest) {
+  switch (dest.value()) {
+    case InCSetState::Young:
+      return &_survivor_plab_stats;
+    case InCSetState::Old:
+      return &_old_plab_stats;
+    default:
+      ShouldNotReachHere();
+      return NULL; // Keep some compilers happy
+  }
+}
+
+size_t G1CollectedHeap::desired_plab_sz(InCSetState dest) {
+  size_t gclab_word_size = alloc_buffer_stats(dest)->desired_plab_sz();
+  // Prevent humongous PLAB sizes for two reasons:
+  // * PLABs are allocated using a similar paths as oops, but should
+  //   never be in a humongous region
+  // * Allowing humongous PLABs needlessly churns the region free lists
+  return MIN2(_humongous_object_threshold_in_words, gclab_word_size);
+}
+
+HeapWord* G1CollectedHeap::par_allocate_during_gc(InCSetState dest,
+                                                  size_t word_size,
+                                                  AllocationContext_t context) {
+  switch (dest.value()) {
+    case InCSetState::Young:
+      return survivor_attempt_allocation(word_size, context);
+    case InCSetState::Old:
+      return old_attempt_allocation(word_size, context);
+    default:
+      ShouldNotReachHere();
+      return NULL; // Keep some compilers happy
+  }
+}
+
 // Inline functions for G1CollectedHeap
 
 inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() {
@@ -96,8 +131,8 @@
 }
 
 inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
-                                                     unsigned int* gc_count_before_ret,
-                                                     int* gclocker_retry_count_ret) {
+                                                     uint* gc_count_before_ret,
+                                                     uint* 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");
@@ -203,7 +238,7 @@
   return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj);
 }
 
-G1CollectedHeap::in_cset_state_t G1CollectedHeap::in_cset_state(const oop obj) {
+InCSetState G1CollectedHeap::in_cset_state(const oop obj) {
   return _in_cset_fast_test.at((HeapWord*)obj);
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1084,7 +1084,7 @@
   if (update_stats) {
     double cost_per_card_ms = 0.0;
     if (_pending_cards > 0) {
-      cost_per_card_ms = phase_times()->average_last_update_rs_time() / (double) _pending_cards;
+      cost_per_card_ms = phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) / (double) _pending_cards;
       _cost_per_card_ms_seq->add(cost_per_card_ms);
     }
 
@@ -1092,7 +1092,7 @@
 
     double cost_per_entry_ms = 0.0;
     if (cards_scanned > 10) {
-      cost_per_entry_ms = phase_times()->average_last_scan_rs_time() / (double) cards_scanned;
+      cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
       if (_last_gc_was_young) {
         _cost_per_entry_ms_seq->add(cost_per_entry_ms);
       } else {
@@ -1134,7 +1134,7 @@
     double cost_per_byte_ms = 0.0;
 
     if (copied_bytes > 0) {
-      cost_per_byte_ms = phase_times()->average_last_obj_copy_time() / (double) copied_bytes;
+      cost_per_byte_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
       if (_in_marking_window) {
         _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
       } else {
@@ -1143,8 +1143,8 @@
     }
 
     double all_other_time_ms = pause_time_ms -
-      (phase_times()->average_last_update_rs_time() + phase_times()->average_last_scan_rs_time()
-      + phase_times()->average_last_obj_copy_time() + phase_times()->average_last_termination_time());
+      (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) + phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) +
+          phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) + phase_times()->average_time_ms(G1GCPhaseTimes::Termination));
 
     double young_other_time_ms = 0.0;
     if (young_cset_region_length() > 0) {
@@ -1185,8 +1185,8 @@
 
   // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
   double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
-  adjust_concurrent_refinement(phase_times()->average_last_update_rs_time(),
-                               phase_times()->sum_last_update_rs_processed_buffers(), update_rs_time_goal_ms);
+  adjust_concurrent_refinement(phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS),
+                               phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS), update_rs_time_goal_ms);
 
   _collectionSetChooser->verify();
 }
@@ -1437,18 +1437,6 @@
   return young_list_length < young_list_max_length;
 }
 
-uint G1CollectorPolicy::max_regions(int purpose) {
-  switch (purpose) {
-    case GCAllocForSurvived:
-      return _max_survivor_regions;
-    case GCAllocForTenured:
-      return REGIONS_UNLIMITED;
-    default:
-      ShouldNotReachHere();
-      return REGIONS_UNLIMITED;
-  };
-}
-
 void G1CollectorPolicy::update_max_gc_locker_expansion() {
   uint expansion_region_num = 0;
   if (GCLockerEdenExpansionPercent > 0) {
@@ -1683,7 +1671,7 @@
   hr->set_next_in_collection_set(_collection_set);
   _collection_set = hr;
   _collection_set_bytes_used_before += hr->used();
-  _g1->register_region_with_in_cset_fast_test(hr);
+  _g1->register_old_region_with_in_cset_fast_test(hr);
   size_t rs_length = hr->rem_set()->occupied();
   _recorded_rs_lengths += rs_length;
   _old_cset_region_length += 1;
@@ -1816,7 +1804,7 @@
   hr->set_in_collection_set(true);
   assert( hr->next_in_collection_set() == NULL, "invariant");
 
-  _g1->register_region_with_in_cset_fast_test(hr);
+  _g1->register_young_region_with_in_cset_fast_test(hr);
 }
 
 // Add the region at the RHS of the incremental cset
@@ -2189,19 +2177,19 @@
     _other.add(pause_time_ms - phase_times->accounted_time_ms());
     _root_region_scan_wait.add(phase_times->root_region_scan_wait_time_ms());
     _parallel.add(phase_times->cur_collection_par_time_ms());
-    _ext_root_scan.add(phase_times->average_last_ext_root_scan_time());
-    _satb_filtering.add(phase_times->average_last_satb_filtering_times_ms());
-    _update_rs.add(phase_times->average_last_update_rs_time());
-    _scan_rs.add(phase_times->average_last_scan_rs_time());
-    _obj_copy.add(phase_times->average_last_obj_copy_time());
-    _termination.add(phase_times->average_last_termination_time());
+    _ext_root_scan.add(phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan));
+    _satb_filtering.add(phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering));
+    _update_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS));
+    _scan_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::ScanRS));
+    _obj_copy.add(phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy));
+    _termination.add(phase_times->average_time_ms(G1GCPhaseTimes::Termination));
 
-    double parallel_known_time = phase_times->average_last_ext_root_scan_time() +
-      phase_times->average_last_satb_filtering_times_ms() +
-      phase_times->average_last_update_rs_time() +
-      phase_times->average_last_scan_rs_time() +
-      phase_times->average_last_obj_copy_time() +
-      + phase_times->average_last_termination_time();
+    double parallel_known_time = phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan) +
+      phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering) +
+      phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS) +
+      phase_times->average_time_ms(G1GCPhaseTimes::ScanRS) +
+      phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy) +
+      phase_times->average_time_ms(G1GCPhaseTimes::Termination);
 
     double parallel_other_time = phase_times->cur_collection_par_time_ms() - parallel_known_time;
     _parallel_other.add(parallel_other_time);
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -877,28 +877,20 @@
 public:
   uint tenuring_threshold() const { return _tenuring_threshold; }
 
-  inline GCAllocPurpose
-    evacuation_destination(HeapRegion* src_region, uint age, size_t word_sz) {
-      if (age < _tenuring_threshold && src_region->is_young()) {
-        return GCAllocForSurvived;
-      } else {
-        return GCAllocForTenured;
-      }
-  }
-
-  inline bool track_object_age(GCAllocPurpose purpose) {
-    return purpose == GCAllocForSurvived;
-  }
-
   static const uint REGIONS_UNLIMITED = (uint) -1;
 
-  uint max_regions(int purpose);
-
-  // The limit on regions for a particular purpose is reached.
-  void note_alloc_region_limit_reached(int purpose) {
-    if (purpose == GCAllocForSurvived) {
-      _tenuring_threshold = 0;
+  uint max_regions(InCSetState dest) {
+    switch (dest.value()) {
+      case InCSetState::Young:
+        return _max_survivor_regions;
+      case InCSetState::Old:
+        return REGIONS_UNLIMITED;
+      default:
+        assert(false, err_msg("Unknown dest state: " CSETSTATE_FORMAT, dest.value()));
+        break;
     }
+    // keep some compilers happy
+    return 0;
   }
 
   void note_start_adding_survivor_regions() {
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -22,12 +22,13 @@
  *
  */
 
-
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1GCPhaseTimes.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1StringDedup.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/os.hpp"
 
 // Helper class for avoiding interleaved logging
 class LineBuffer: public StackObj {
@@ -70,184 +71,258 @@
     va_end(ap);
   }
 
+  void print_cr() {
+    gclog_or_tty->print_cr("%s", _buffer);
+    _cur = _indent_level * INDENT_CHARS;
+  }
+
   void append_and_print_cr(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3) {
     va_list ap;
     va_start(ap, format);
     vappend(format, ap);
     va_end(ap);
-    gclog_or_tty->print_cr("%s", _buffer);
-    _cur = _indent_level * INDENT_CHARS;
+    print_cr();
   }
 };
 
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED
 template <class T>
-void WorkerDataArray<T>::print(int level, const char* title) {
-  if (_length == 1) {
-    // No need for min, max, average and sum for only one worker
-    LineBuffer buf(level);
-    buf.append("[%s:  ", title);
-    buf.append(_print_format, _data[0]);
-    buf.append_and_print_cr("]");
-    return;
+class WorkerDataArray  : public CHeapObj<mtGC> {
+  friend class G1GCParPhasePrinter;
+  T*          _data;
+  uint        _length;
+  const char* _title;
+  bool        _print_sum;
+  int         _log_level;
+  uint        _indent_level;
+  bool        _enabled;
+
+  WorkerDataArray<size_t>* _thread_work_items;
+
+  NOT_PRODUCT(T uninitialized();)
+
+  // We are caching the sum and average to only have to calculate them once.
+  // This is not done in an MT-safe way. It is intended to allow single
+  // threaded code to call sum() and average() multiple times in any order
+  // without having to worry about the cost.
+  bool   _has_new_data;
+  T      _sum;
+  T      _min;
+  T      _max;
+  double _average;
+
+ public:
+  WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level) :
+    _title(title), _length(0), _print_sum(print_sum), _log_level(log_level), _indent_level(indent_level),
+    _has_new_data(true), _thread_work_items(NULL), _enabled(true) {
+    assert(length > 0, "Must have some workers to store data for");
+    _length = length;
+    _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
+  }
+
+  ~WorkerDataArray() {
+    FREE_C_HEAP_ARRAY(T, _data, mtGC);
+  }
+
+  void link_thread_work_items(WorkerDataArray<size_t>* thread_work_items) {
+    _thread_work_items = thread_work_items;
+  }
+
+  WorkerDataArray<size_t>* thread_work_items() { return _thread_work_items; }
+
+  void set(uint worker_i, T value) {
+    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
+    assert(_data[worker_i] == WorkerDataArray<T>::uninitialized(), err_msg("Overwriting data for worker %d in %s", worker_i, _title));
+    _data[worker_i] = value;
+    _has_new_data = true;
+  }
+
+  void set_thread_work_item(uint worker_i, size_t value) {
+    assert(_thread_work_items != NULL, "No sub count");
+    _thread_work_items->set(worker_i, value);
   }
 
-  T min = _data[0];
-  T max = _data[0];
-  T sum = 0;
+  T get(uint worker_i) {
+    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
+    assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data added for worker %d", worker_i));
+    return _data[worker_i];
+  }
+
+  void add(uint worker_i, T value) {
+    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
+    assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data to add to for worker %d", worker_i));
+    _data[worker_i] += value;
+    _has_new_data = true;
+  }
 
-  LineBuffer buf(level);
-  buf.append("[%s:", title);
-  for (uint i = 0; i < _length; ++i) {
-    T val = _data[i];
-    min = MIN2(val, min);
-    max = MAX2(val, max);
-    sum += val;
-    if (G1Log::finest()) {
-      buf.append("  ");
-      buf.append(_print_format, val);
-    }
+  double average(){
+    calculate_totals();
+    return _average;
+  }
+
+  T sum() {
+    calculate_totals();
+    return _sum;
+  }
+
+  T minimum() {
+    calculate_totals();
+    return _min;
   }
 
-  if (G1Log::finest()) {
-    buf.append_and_print_cr("%s", "");
+  T maximum() {
+    calculate_totals();
+    return _max;
   }
 
-  double avg = (double)sum / (double)_length;
-  buf.append(" Min: ");
-  buf.append(_print_format, min);
-  buf.append(", Avg: ");
-  buf.append("%.1lf", avg); // Always print average as a double
-  buf.append(", Max: ");
-  buf.append(_print_format, max);
-  buf.append(", Diff: ");
-  buf.append(_print_format, max - min);
-  if (_print_sum) {
-    // for things like the start and end times the sum is not
-    // that relevant
-    buf.append(", Sum: ");
-    buf.append(_print_format, sum);
+  void reset() PRODUCT_RETURN;
+  void verify() PRODUCT_RETURN;
+
+  void set_enabled(bool enabled) { _enabled = enabled; }
+
+  int log_level() { return _log_level;  }
+
+ private:
+
+  void calculate_totals(){
+    if (!_has_new_data) {
+      return;
+    }
+
+    _sum = (T)0;
+    _min = _data[0];
+    _max = _min;
+    for (uint i = 0; i < _length; ++i) {
+      T val = _data[i];
+      _sum += val;
+      _min = MIN2(_min, val);
+      _max = MAX2(_max, val);
+    }
+    _average = (double)_sum / (double)_length;
+    _has_new_data = false;
   }
-  buf.append_and_print_cr("]");
-}
-PRAGMA_DIAG_POP
+};
+
 
 #ifndef PRODUCT
 
-template <> const int WorkerDataArray<int>::_uninitialized = -1;
-template <> const double WorkerDataArray<double>::_uninitialized = -1.0;
-template <> const size_t WorkerDataArray<size_t>::_uninitialized = (size_t)-1;
+template <>
+size_t WorkerDataArray<size_t>::uninitialized() {
+  return (size_t)-1;
+}
+
+template <>
+double WorkerDataArray<double>::uninitialized() {
+  return -1.0;
+}
 
 template <class T>
 void WorkerDataArray<T>::reset() {
   for (uint i = 0; i < _length; i++) {
-    _data[i] = (T)_uninitialized;
+    _data[i] = WorkerDataArray<T>::uninitialized();
+  }
+  if (_thread_work_items != NULL) {
+    _thread_work_items->reset();
   }
 }
 
 template <class T>
 void WorkerDataArray<T>::verify() {
+  if (!_enabled) {
+    return;
+  }
+
   for (uint i = 0; i < _length; i++) {
-    assert(_data[i] != _uninitialized,
-        err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf",
-            i, (double)_data[i], (double)_uninitialized));
+    assert(_data[i] != WorkerDataArray<T>::uninitialized(),
+        err_msg("Invalid data for worker %u in '%s'", i, _title));
+  }
+  if (_thread_work_items != NULL) {
+    _thread_work_items->verify();
   }
 }
 
 #endif
 
 G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
-  _max_gc_threads(max_gc_threads),
-  _last_gc_worker_start_times_ms(_max_gc_threads, "%.1lf", false),
-  _last_ext_root_scan_times_ms(_max_gc_threads, "%.1lf"),
-  _last_satb_filtering_times_ms(_max_gc_threads, "%.1lf"),
-  _last_update_rs_times_ms(_max_gc_threads, "%.1lf"),
-  _last_update_rs_processed_buffers(_max_gc_threads, "%d"),
-  _last_scan_rs_times_ms(_max_gc_threads, "%.1lf"),
-  _last_strong_code_root_scan_times_ms(_max_gc_threads, "%.1lf"),
-  _last_obj_copy_times_ms(_max_gc_threads, "%.1lf"),
-  _last_termination_times_ms(_max_gc_threads, "%.1lf"),
-  _last_termination_attempts(_max_gc_threads, SIZE_FORMAT),
-  _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false),
-  _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"),
-  _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"),
-  _last_redirty_logged_cards_time_ms(_max_gc_threads, "%.1lf"),
-  _last_redirty_logged_cards_processed_cards(_max_gc_threads, SIZE_FORMAT),
-  _cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"),
-  _cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf")
+  _max_gc_threads(max_gc_threads)
 {
   assert(max_gc_threads > 0, "Must have some GC threads");
+
+  _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start (ms)", false, G1Log::LevelFiner, 2);
+  _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning (ms)", true, G1Log::LevelFiner, 2);
+
+  // Root scanning phases
+  _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[StringTableRoots] = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[CodeCacheRoots] = new WorkerDataArray<double>(max_gc_threads, "CodeCache Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms)", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFinest, 3);
+
+  _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[Termination] = new WorkerDataArray<double>(max_gc_threads, "Termination (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Total (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>(max_gc_threads, "GC Worker End (ms)", false, G1Log::LevelFiner, 2);
+  _gc_par_phases[Other] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Other (ms)", true, G1Log::LevelFiner, 2);
+
+  _update_rs_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers", true, G1Log::LevelFiner, 3);
+  _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers);
+
+  _termination_attempts = new WorkerDataArray<size_t>(max_gc_threads, "Termination Attempts", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts);
+
+  _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray<double>(max_gc_threads, "Queue Fixup (ms)", true, G1Log::LevelFiner, 2);
+  _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray<double>(max_gc_threads, "Table Fixup (ms)", true, G1Log::LevelFiner, 2);
+
+  _gc_par_phases[RedirtyCards] = new WorkerDataArray<double>(max_gc_threads, "Parallel Redirty", true, G1Log::LevelFinest, 3);
+  _redirtied_cards = new WorkerDataArray<size_t>(max_gc_threads, "Redirtied Cards", true, G1Log::LevelFinest, 3);
+  _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards);
 }
 
-void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) {
+void G1GCPhaseTimes::note_gc_start(uint active_gc_threads, bool mark_in_progress) {
   assert(active_gc_threads > 0, "The number of threads must be > 0");
-  assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max nubmer of threads");
+  assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads");
   _active_gc_threads = active_gc_threads;
 
-  _last_gc_worker_start_times_ms.reset();
-  _last_ext_root_scan_times_ms.reset();
-  _last_satb_filtering_times_ms.reset();
-  _last_update_rs_times_ms.reset();
-  _last_update_rs_processed_buffers.reset();
-  _last_scan_rs_times_ms.reset();
-  _last_strong_code_root_scan_times_ms.reset();
-  _last_obj_copy_times_ms.reset();
-  _last_termination_times_ms.reset();
-  _last_termination_attempts.reset();
-  _last_gc_worker_end_times_ms.reset();
-  _last_gc_worker_times_ms.reset();
-  _last_gc_worker_other_times_ms.reset();
+  for (int i = 0; i < GCParPhasesSentinel; i++) {
+    _gc_par_phases[i]->reset();
+  }
 
-  _last_redirty_logged_cards_time_ms.reset();
-  _last_redirty_logged_cards_processed_cards.reset();
-
+  _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled());
+  _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled());
 }
 
 void G1GCPhaseTimes::note_gc_end() {
-  _last_gc_worker_start_times_ms.verify();
-  _last_ext_root_scan_times_ms.verify();
-  _last_satb_filtering_times_ms.verify();
-  _last_update_rs_times_ms.verify();
-  _last_update_rs_processed_buffers.verify();
-  _last_scan_rs_times_ms.verify();
-  _last_strong_code_root_scan_times_ms.verify();
-  _last_obj_copy_times_ms.verify();
-  _last_termination_times_ms.verify();
-  _last_termination_attempts.verify();
-  _last_gc_worker_end_times_ms.verify();
+  for (uint i = 0; i < _active_gc_threads; i++) {
+    double worker_time = _gc_par_phases[GCWorkerEnd]->get(i) - _gc_par_phases[GCWorkerStart]->get(i);
+    record_time_secs(GCWorkerTotal, i , worker_time);
 
-  for (uint i = 0; i < _active_gc_threads; i++) {
-    double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i);
-    _last_gc_worker_times_ms.set(i, worker_time);
+    double worker_known_time =
+        _gc_par_phases[ExtRootScan]->get(i) +
+        _gc_par_phases[SATBFiltering]->get(i) +
+        _gc_par_phases[UpdateRS]->get(i) +
+        _gc_par_phases[ScanRS]->get(i) +
+        _gc_par_phases[CodeRoots]->get(i) +
+        _gc_par_phases[ObjCopy]->get(i) +
+        _gc_par_phases[Termination]->get(i);
 
-    double worker_known_time = _last_ext_root_scan_times_ms.get(i) +
-                               _last_satb_filtering_times_ms.get(i) +
-                               _last_update_rs_times_ms.get(i) +
-                               _last_scan_rs_times_ms.get(i) +
-                               _last_strong_code_root_scan_times_ms.get(i) +
-                               _last_obj_copy_times_ms.get(i) +
-                               _last_termination_times_ms.get(i);
-
-    double worker_other_time = worker_time - worker_known_time;
-    _last_gc_worker_other_times_ms.set(i, worker_other_time);
+    record_time_secs(Other, i, worker_time - worker_known_time);
   }
 
-  _last_gc_worker_times_ms.verify();
-  _last_gc_worker_other_times_ms.verify();
-
-  _last_redirty_logged_cards_time_ms.verify();
-  _last_redirty_logged_cards_processed_cards.verify();
-}
-
-void G1GCPhaseTimes::note_string_dedup_fixup_start() {
-  _cur_string_dedup_queue_fixup_worker_times_ms.reset();
-  _cur_string_dedup_table_fixup_worker_times_ms.reset();
-}
-
-void G1GCPhaseTimes::note_string_dedup_fixup_end() {
-  _cur_string_dedup_queue_fixup_worker_times_ms.verify();
-  _cur_string_dedup_table_fixup_worker_times_ms.verify();
+  for (int i = 0; i < GCParPhasesSentinel; i++) {
+    _gc_par_phases[i]->verify();
+  }
 }
 
 void G1GCPhaseTimes::print_stats(int level, const char* str, double value) {
@@ -259,7 +334,7 @@
 }
 
 void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) {
-  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: " UINT32_FORMAT "]", str, value, workers);
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers);
 }
 
 double G1GCPhaseTimes::accounted_time_ms() {
@@ -287,46 +362,172 @@
     return misc_time_ms;
 }
 
+// record the time a phase took in seconds
+void G1GCPhaseTimes::record_time_secs(GCParPhases phase, uint worker_i, double secs) {
+  _gc_par_phases[phase]->set(worker_i, secs);
+}
+
+// add a number of seconds to a phase
+void G1GCPhaseTimes::add_time_secs(GCParPhases phase, uint worker_i, double secs) {
+  _gc_par_phases[phase]->add(worker_i, secs);
+}
+
+void G1GCPhaseTimes::record_thread_work_item(GCParPhases phase, uint worker_i, size_t count) {
+  _gc_par_phases[phase]->set_thread_work_item(worker_i, count);
+}
+
+// return the average time for a phase in milliseconds
+double G1GCPhaseTimes::average_time_ms(GCParPhases phase) {
+  return _gc_par_phases[phase]->average() * 1000.0;
+}
+
+double G1GCPhaseTimes::get_time_ms(GCParPhases phase, uint worker_i) {
+  return _gc_par_phases[phase]->get(worker_i) * 1000.0;
+}
+
+double G1GCPhaseTimes::sum_time_ms(GCParPhases phase) {
+  return _gc_par_phases[phase]->sum() * 1000.0;
+}
+
+double G1GCPhaseTimes::min_time_ms(GCParPhases phase) {
+  return _gc_par_phases[phase]->minimum() * 1000.0;
+}
+
+double G1GCPhaseTimes::max_time_ms(GCParPhases phase) {
+  return _gc_par_phases[phase]->maximum() * 1000.0;
+}
+
+size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i) {
+  assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
+  return _gc_par_phases[phase]->thread_work_items()->get(worker_i);
+}
+
+size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) {
+  assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
+  return _gc_par_phases[phase]->thread_work_items()->sum();
+}
+
+double G1GCPhaseTimes::average_thread_work_items(GCParPhases phase) {
+  assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
+  return _gc_par_phases[phase]->thread_work_items()->average();
+}
+
+size_t G1GCPhaseTimes::min_thread_work_items(GCParPhases phase) {
+  assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
+  return _gc_par_phases[phase]->thread_work_items()->minimum();
+}
+
+size_t G1GCPhaseTimes::max_thread_work_items(GCParPhases phase) {
+  assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
+  return _gc_par_phases[phase]->thread_work_items()->maximum();
+}
+
+class G1GCParPhasePrinter : public StackObj {
+  G1GCPhaseTimes* _phase_times;
+ public:
+  G1GCParPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {}
+
+  void print(G1GCPhaseTimes::GCParPhases phase_id) {
+    WorkerDataArray<double>* phase = _phase_times->_gc_par_phases[phase_id];
+
+    if (phase->_log_level > G1Log::level() || !phase->_enabled) {
+      return;
+    }
+
+    if (phase->_length == 1) {
+      print_single_length(phase_id, phase);
+    } else {
+      print_multi_length(phase_id, phase);
+    }
+  }
+
+ private:
+
+  void print_single_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<double>* phase) {
+    // No need for min, max, average and sum for only one worker
+    LineBuffer buf(phase->_indent_level);
+    buf.append_and_print_cr("[%s:  %.1lf]", phase->_title, _phase_times->get_time_ms(phase_id, 0));
+
+    if (phase->_thread_work_items != NULL) {
+      LineBuffer buf2(phase->_thread_work_items->_indent_level);
+      buf2.append_and_print_cr("[%s:  "SIZE_FORMAT"]", phase->_thread_work_items->_title, _phase_times->sum_thread_work_items(phase_id));
+    }
+  }
+
+  void print_time_values(LineBuffer& buf, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<double>* phase) {
+    for (uint i = 0; i < phase->_length; ++i) {
+      buf.append("  %.1lf", _phase_times->get_time_ms(phase_id, i));
+    }
+    buf.print_cr();
+  }
+
+  void print_count_values(LineBuffer& buf, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<size_t>* thread_work_items) {
+    for (uint i = 0; i < thread_work_items->_length; ++i) {
+      buf.append("  " SIZE_FORMAT, _phase_times->get_thread_work_item(phase_id, i));
+    }
+    buf.print_cr();
+  }
+
+  void print_thread_work_items(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<size_t>* thread_work_items) {
+    LineBuffer buf(thread_work_items->_indent_level);
+    buf.append("[%s:", thread_work_items->_title);
+
+    if (G1Log::finest()) {
+      print_count_values(buf, phase_id, thread_work_items);
+    }
+
+    assert(thread_work_items->_print_sum, err_msg("%s does not have print sum true even though it is a count", thread_work_items->_title));
+
+    buf.append_and_print_cr(" Min: " SIZE_FORMAT ", Avg: %.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT "]",
+        _phase_times->min_thread_work_items(phase_id), _phase_times->average_thread_work_items(phase_id), _phase_times->max_thread_work_items(phase_id),
+        _phase_times->max_thread_work_items(phase_id) - _phase_times->min_thread_work_items(phase_id), _phase_times->sum_thread_work_items(phase_id));
+  }
+
+  void print_multi_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<double>* phase) {
+    LineBuffer buf(phase->_indent_level);
+    buf.append("[%s:", phase->_title);
+
+    if (G1Log::finest()) {
+      print_time_values(buf, phase_id, phase);
+    }
+
+    buf.append(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf",
+        _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id),
+        _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id));
+
+    if (phase->_print_sum) {
+      // for things like the start and end times the sum is not
+      // that relevant
+      buf.append(", Sum: %.1lf", _phase_times->sum_time_ms(phase_id));
+    }
+
+    buf.append_and_print_cr("]");
+
+    if (phase->_thread_work_items != NULL) {
+      print_thread_work_items(phase_id, phase->_thread_work_items);
+    }
+  }
+};
+
 void G1GCPhaseTimes::print(double pause_time_sec) {
+  G1GCParPhasePrinter par_phase_printer(this);
+
   if (_root_region_scan_wait_time_ms > 0.0) {
     print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
   }
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads);
-    _last_gc_worker_start_times_ms.print(2, "GC Worker Start (ms)");
-    _last_ext_root_scan_times_ms.print(2, "Ext Root Scanning (ms)");
-    if (_last_satb_filtering_times_ms.sum() > 0.0) {
-      _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)");
-    }
-    _last_update_rs_times_ms.print(2, "Update RS (ms)");
-      _last_update_rs_processed_buffers.print(3, "Processed Buffers");
-    _last_scan_rs_times_ms.print(2, "Scan RS (ms)");
-    _last_strong_code_root_scan_times_ms.print(2, "Code Root Scanning (ms)");
-    _last_obj_copy_times_ms.print(2, "Object Copy (ms)");
-    _last_termination_times_ms.print(2, "Termination (ms)");
-    if (G1Log::finest()) {
-      _last_termination_attempts.print(3, "Termination Attempts");
-    }
-    _last_gc_worker_other_times_ms.print(2, "GC Worker Other (ms)");
-    _last_gc_worker_times_ms.print(2, "GC Worker Total (ms)");
-    _last_gc_worker_end_times_ms.print(2, "GC Worker End (ms)");
-  } else {
-    _last_ext_root_scan_times_ms.print(1, "Ext Root Scanning (ms)");
-    if (_last_satb_filtering_times_ms.sum() > 0.0) {
-      _last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)");
-    }
-    _last_update_rs_times_ms.print(1, "Update RS (ms)");
-      _last_update_rs_processed_buffers.print(2, "Processed Buffers");
-    _last_scan_rs_times_ms.print(1, "Scan RS (ms)");
-    _last_strong_code_root_scan_times_ms.print(1, "Code Root Scanning (ms)");
-    _last_obj_copy_times_ms.print(1, "Object Copy (ms)");
+
+  print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads);
+  for (int i = 0; i <= GCMainParPhasesLast; i++) {
+    par_phase_printer.print((GCParPhases) i);
   }
+
   print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
   print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms);
   if (G1StringDedup::is_enabled()) {
     print_stats(1, "String Dedup Fixup", _cur_string_dedup_fixup_time_ms, _active_gc_threads);
-    _cur_string_dedup_queue_fixup_worker_times_ms.print(2, "Queue Fixup (ms)");
-    _cur_string_dedup_table_fixup_worker_times_ms.print(2, "Table Fixup (ms)");
+    for (int i = StringDedupPhasesFirst; i <= StringDedupPhasesLast; i++) {
+      par_phase_printer.print((GCParPhases) i);
+    }
   }
   print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
   double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms();
@@ -350,10 +551,7 @@
   print_stats(2, "Ref Proc", _cur_ref_proc_time_ms);
   print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
   print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
-  if (G1Log::finest()) {
-    _last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
-    _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
-  }
+  par_phase_printer.print(RedirtyCards);
   if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
     print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
     if (G1Log::finest()) {
@@ -373,3 +571,17 @@
     print_stats(2, "Verify After", _cur_verify_after_time_ms);
   }
 }
+
+G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) :
+    _phase_times(phase_times), _phase(phase), _worker_id(worker_id) {
+  if (_phase_times != NULL) {
+    _start_time = os::elapsedTime();
+  }
+}
+
+G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() {
+  if (_phase_times != NULL) {
+    _phase_times->record_time_secs(_phase, _worker_id, os::elapsedTime() - _start_time);
+  }
+}
+
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -26,106 +26,60 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
 
 #include "memory/allocation.hpp"
-#include "gc_interface/gcCause.hpp"
-
-template <class T>
-class WorkerDataArray  : public CHeapObj<mtGC> {
-  T*          _data;
-  uint        _length;
-  const char* _print_format;
-  bool        _print_sum;
-
-  NOT_PRODUCT(static const T _uninitialized;)
-
-  // We are caching the sum and average to only have to calculate them once.
-  // This is not done in an MT-safe way. It is intended to allow single
-  // threaded code to call sum() and average() multiple times in any order
-  // without having to worry about the cost.
-  bool   _has_new_data;
-  T      _sum;
-  double _average;
-
- public:
-  WorkerDataArray(uint length, const char* print_format, bool print_sum = true) :
-  _length(length), _print_format(print_format), _print_sum(print_sum), _has_new_data(true) {
-    assert(length > 0, "Must have some workers to store data for");
-    _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
-  }
-
-  ~WorkerDataArray() {
-    FREE_C_HEAP_ARRAY(T, _data, mtGC);
-  }
-
-  void set(uint worker_i, T value) {
-    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
-    assert(_data[worker_i] == (T)-1, err_msg("Overwriting data for worker %d", worker_i));
-    _data[worker_i] = value;
-    _has_new_data = true;
-  }
 
-  T get(uint worker_i) {
-    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
-    assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
-    return _data[worker_i];
-  }
-
-  void add(uint worker_i, T value) {
-    assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
-    assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
-    _data[worker_i] += value;
-    _has_new_data = true;
-  }
-
-  double average(){
-    if (_has_new_data) {
-      calculate_totals();
-    }
-    return _average;
-  }
+class LineBuffer;
 
-  T sum() {
-    if (_has_new_data) {
-      calculate_totals();
-    }
-    return _sum;
-  }
-
-  void print(int level, const char* title);
-
-  void reset() PRODUCT_RETURN;
-  void verify() PRODUCT_RETURN;
-
- private:
-
-  void calculate_totals(){
-    _sum = (T)0;
-    for (uint i = 0; i < _length; ++i) {
-      _sum += _data[i];
-    }
-    _average = (double)_sum / (double)_length;
-    _has_new_data = false;
-  }
-};
+template <class T> class WorkerDataArray;
 
 class G1GCPhaseTimes : public CHeapObj<mtGC> {
+  friend class G1GCParPhasePrinter;
 
- private:
   uint _active_gc_threads;
   uint _max_gc_threads;
 
-  WorkerDataArray<double> _last_gc_worker_start_times_ms;
-  WorkerDataArray<double> _last_ext_root_scan_times_ms;
-  WorkerDataArray<double> _last_satb_filtering_times_ms;
-  WorkerDataArray<double> _last_update_rs_times_ms;
-  WorkerDataArray<int>    _last_update_rs_processed_buffers;
-  WorkerDataArray<double> _last_scan_rs_times_ms;
-  WorkerDataArray<double> _last_strong_code_root_scan_times_ms;
-  WorkerDataArray<double> _last_obj_copy_times_ms;
-  WorkerDataArray<double> _last_termination_times_ms;
-  WorkerDataArray<size_t> _last_termination_attempts;
-  WorkerDataArray<double> _last_gc_worker_end_times_ms;
-  WorkerDataArray<double> _last_gc_worker_times_ms;
-  WorkerDataArray<double> _last_gc_worker_other_times_ms;
+ public:
+  enum GCParPhases {
+    GCWorkerStart,
+    ExtRootScan,
+    ThreadRoots,
+    StringTableRoots,
+    UniverseRoots,
+    JNIRoots,
+    ObjectSynchronizerRoots,
+    FlatProfilerRoots,
+    ManagementRoots,
+    SystemDictionaryRoots,
+    CLDGRoots,
+    JVMTIRoots,
+    CodeCacheRoots,
+    CMRefRoots,
+    WaitForStrongCLD,
+    WeakCLDRoots,
+    SATBFiltering,
+    UpdateRS,
+    ScanRS,
+    CodeRoots,
+    ObjCopy,
+    Termination,
+    Other,
+    GCWorkerTotal,
+    GCWorkerEnd,
+    StringDedupQueueFixup,
+    StringDedupTableFixup,
+    RedirtyCards,
+    GCParPhasesSentinel
+  };
+
+ private:
+  // Markers for grouping the phases in the GCPhases enum above
+  static const int GCMainParPhasesLast = GCWorkerEnd;
+  static const int StringDedupPhasesFirst = StringDedupQueueFixup;
+  static const int StringDedupPhasesLast = StringDedupTableFixup;
+
+  WorkerDataArray<double>* _gc_par_phases[GCParPhasesSentinel];
+  WorkerDataArray<size_t>* _update_rs_processed_buffers;
+  WorkerDataArray<size_t>* _termination_attempts;
+  WorkerDataArray<size_t>* _redirtied_cards;
 
   double _cur_collection_par_time_ms;
   double _cur_collection_code_root_fixup_time_ms;
@@ -135,9 +89,7 @@
   double _cur_evac_fail_restore_remsets;
   double _cur_evac_fail_remove_self_forwards;
 
-  double                  _cur_string_dedup_fixup_time_ms;
-  WorkerDataArray<double> _cur_string_dedup_queue_fixup_worker_times_ms;
-  WorkerDataArray<double> _cur_string_dedup_table_fixup_worker_times_ms;
+  double _cur_string_dedup_fixup_time_ms;
 
   double _cur_clear_ct_time_ms;
   double _cur_ref_proc_time_ms;
@@ -149,8 +101,6 @@
   double _recorded_young_cset_choice_time_ms;
   double _recorded_non_young_cset_choice_time_ms;
 
-  WorkerDataArray<double> _last_redirty_logged_cards_time_ms;
-  WorkerDataArray<size_t> _last_redirty_logged_cards_processed_cards;
   double _recorded_redirty_logged_cards_time_ms;
 
   double _recorded_young_free_cset_time_ms;
@@ -171,54 +121,34 @@
 
  public:
   G1GCPhaseTimes(uint max_gc_threads);
-  void note_gc_start(uint active_gc_threads);
+  void note_gc_start(uint active_gc_threads, bool mark_in_progress);
   void note_gc_end();
   void print(double pause_time_sec);
 
-  void record_gc_worker_start_time(uint worker_i, double ms) {
-    _last_gc_worker_start_times_ms.set(worker_i, ms);
-  }
-
-  void record_ext_root_scan_time(uint worker_i, double ms) {
-    _last_ext_root_scan_times_ms.set(worker_i, ms);
-  }
+  // record the time a phase took in seconds
+  void record_time_secs(GCParPhases phase, uint worker_i, double secs);
 
-  void record_satb_filtering_time(uint worker_i, double ms) {
-    _last_satb_filtering_times_ms.set(worker_i, ms);
-  }
+  // add a number of seconds to a phase
+  void add_time_secs(GCParPhases phase, uint worker_i, double secs);
 
-  void record_update_rs_time(uint worker_i, double ms) {
-    _last_update_rs_times_ms.set(worker_i, ms);
-  }
+  void record_thread_work_item(GCParPhases phase, uint worker_i, size_t count);
 
-  void record_update_rs_processed_buffers(uint worker_i, int processed_buffers) {
-    _last_update_rs_processed_buffers.set(worker_i, processed_buffers);
-  }
+  // return the average time for a phase in milliseconds
+  double average_time_ms(GCParPhases phase);
 
-  void record_scan_rs_time(uint worker_i, double ms) {
-    _last_scan_rs_times_ms.set(worker_i, ms);
-  }
-
-  void record_strong_code_root_scan_time(uint worker_i, double ms) {
-    _last_strong_code_root_scan_times_ms.set(worker_i, ms);
-  }
-
-  void record_obj_copy_time(uint worker_i, double ms) {
-    _last_obj_copy_times_ms.set(worker_i, ms);
-  }
+  size_t sum_thread_work_items(GCParPhases phase);
 
-  void add_obj_copy_time(uint worker_i, double ms) {
-    _last_obj_copy_times_ms.add(worker_i, ms);
-  }
+ private:
+  double get_time_ms(GCParPhases phase, uint worker_i);
+  double sum_time_ms(GCParPhases phase);
+  double min_time_ms(GCParPhases phase);
+  double max_time_ms(GCParPhases phase);
+  size_t get_thread_work_item(GCParPhases phase, uint worker_i);
+  double average_thread_work_items(GCParPhases phase);
+  size_t min_thread_work_items(GCParPhases phase);
+  size_t max_thread_work_items(GCParPhases phase);
 
-  void record_termination(uint worker_i, double ms, size_t attempts) {
-    _last_termination_times_ms.set(worker_i, ms);
-    _last_termination_attempts.set(worker_i, attempts);
-  }
-
-  void record_gc_worker_end_time(uint worker_i, double ms) {
-    _last_gc_worker_end_times_ms.set(worker_i, ms);
-  }
+ public:
 
   void record_clear_ct_time(double ms) {
     _cur_clear_ct_time_ms = ms;
@@ -248,21 +178,10 @@
     _cur_evac_fail_remove_self_forwards = ms;
   }
 
-  void note_string_dedup_fixup_start();
-  void note_string_dedup_fixup_end();
-
   void record_string_dedup_fixup_time(double ms) {
     _cur_string_dedup_fixup_time_ms = ms;
   }
 
-  void record_string_dedup_queue_fixup_worker_time(uint worker_id, double ms) {
-    _cur_string_dedup_queue_fixup_worker_times_ms.set(worker_id, ms);
-  }
-
-  void record_string_dedup_table_fixup_worker_time(uint worker_id, double ms) {
-    _cur_string_dedup_table_fixup_worker_times_ms.set(worker_id, ms);
-  }
-
   void record_ref_proc_time(double ms) {
     _cur_ref_proc_time_ms = ms;
   }
@@ -301,14 +220,6 @@
     _recorded_non_young_cset_choice_time_ms = time_ms;
   }
 
-  void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) {
-    _last_redirty_logged_cards_time_ms.set(worker_i, time_ms);
-  }
-
-  void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) {
-    _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers);
-  }
-
   void record_redirty_logged_cards_time_ms(double time_ms) {
     _recorded_redirty_logged_cards_time_ms = time_ms;
   }
@@ -362,38 +273,16 @@
   double fast_reclaim_humongous_time_ms() {
     return _cur_fast_reclaim_humongous_time_ms;
   }
-
-  double average_last_update_rs_time() {
-    return _last_update_rs_times_ms.average();
-  }
-
-  int sum_last_update_rs_processed_buffers() {
-    return _last_update_rs_processed_buffers.sum();
-  }
-
-  double average_last_scan_rs_time(){
-    return _last_scan_rs_times_ms.average();
-  }
+};
 
-  double average_last_strong_code_root_scan_time(){
-    return _last_strong_code_root_scan_times_ms.average();
-  }
-
-  double average_last_obj_copy_time() {
-    return _last_obj_copy_times_ms.average();
-  }
-
-  double average_last_termination_time() {
-    return _last_termination_times_ms.average();
-  }
-
-  double average_last_ext_root_scan_time() {
-    return _last_ext_root_scan_times_ms.average();
-  }
-
-  double average_last_satb_filtering_times_ms() {
-    return _last_satb_filtering_times_ms.average();
-  }
+class G1GCParPhaseTimesTracker : public StackObj {
+  double _start_time;
+  G1GCPhaseTimes::GCParPhases _phase;
+  G1GCPhaseTimes* _phase_times;
+  uint _worker_id;
+public:
+  G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id);
+  ~G1GCParPhaseTimesTracker();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
--- a/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,16 +36,13 @@
   if (default_use_cache()) {
     _use_cache = true;
 
-    _hot_cache_size = (1 << G1ConcRSLogCacheSize);
+    _hot_cache_size = (size_t)1 << G1ConcRSLogCacheSize;
     _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size, mtGC);
 
-    _n_hot = 0;
-    _hot_cache_idx = 0;
+    reset_hot_cache_internal();
 
     // For refining the cards in the hot cache in parallel
-    uint n_workers = (ParallelGCThreads > 0 ?
-                        _g1h->workers()->total_workers() : 1);
-    _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers);
+    _hot_cache_par_chunk_size = (int)(ParallelGCThreads > 0 ? ClaimChunkSize : _hot_cache_size);
     _hot_cache_par_claimed_idx = 0;
 
     _card_counts.initialize(card_counts_storage);
@@ -66,26 +63,21 @@
     // return it for immediate refining.
     return card_ptr;
   }
-
   // Otherwise, the card is hot.
-  jbyte* res = NULL;
-  MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag);
-  if (_n_hot == _hot_cache_size) {
-    res = _hot_cache[_hot_cache_idx];
-    _n_hot--;
-  }
+  size_t index = Atomic::add_ptr((intptr_t)1, (volatile intptr_t*)&_hot_cache_idx) - 1;
+  size_t masked_index = index & (_hot_cache_size - 1);
+  jbyte* current_ptr = _hot_cache[masked_index];
 
-  // Now _n_hot < _hot_cache_size, and we can insert at _hot_cache_idx.
-  _hot_cache[_hot_cache_idx] = card_ptr;
-  _hot_cache_idx++;
-
-  if (_hot_cache_idx == _hot_cache_size) {
-    // Wrap around
-    _hot_cache_idx = 0;
-  }
-  _n_hot++;
-
-  return res;
+  // Try to store the new card pointer into the cache. Compare-and-swap to guard
+  // against the unlikely event of a race resulting in another card pointer to
+  // have already been written to the cache. In this case we will return
+  // card_ptr in favor of the other option, which would be starting over. This
+  // should be OK since card_ptr will likely be the older card already when/if
+  // this ever happens.
+  jbyte* previous_ptr = (jbyte*)Atomic::cmpxchg_ptr(card_ptr,
+                                                    &_hot_cache[masked_index],
+                                                    current_ptr);
+  return (previous_ptr == current_ptr) ? previous_ptr : card_ptr;
 }
 
 void G1HotCardCache::drain(uint worker_i,
@@ -98,38 +90,37 @@
 
   assert(_hot_cache != NULL, "Logic");
   assert(!use_cache(), "cache should be disabled");
-  int start_idx;
-
-  while ((start_idx = _hot_cache_par_claimed_idx) < _n_hot) { // read once
-    int end_idx = start_idx + _hot_cache_par_chunk_size;
+  while (_hot_cache_par_claimed_idx < _hot_cache_size) {
+    size_t end_idx = Atomic::add_ptr((intptr_t)_hot_cache_par_chunk_size,
+                                     (volatile intptr_t*)&_hot_cache_par_claimed_idx);
+    size_t start_idx = end_idx - _hot_cache_par_chunk_size;
+    // The current worker has successfully claimed the chunk [start_idx..end_idx)
+    end_idx = MIN2(end_idx, _hot_cache_size);
+    for (size_t i = start_idx; i < end_idx; i++) {
+      jbyte* card_ptr = _hot_cache[i];
+      if (card_ptr != NULL) {
+        if (g1rs->refine_card(card_ptr, worker_i, true)) {
+          // The part of the heap spanned by the card contains references
+          // that point into the current collection set.
+          // We need to record the card pointer in the DirtyCardQueueSet
+          // that we use for such cards.
+          //
+          // The only time we care about recording cards that contain
+          // references that point into the collection set is during
+          // RSet updating while within an evacuation pause.
+          // In this case worker_i should be the id of a GC worker thread
+          assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
+          assert(worker_i < ParallelGCThreads,
+                 err_msg("incorrect worker id: %u", worker_i));
 
-    if (start_idx ==
-        Atomic::cmpxchg(end_idx, &_hot_cache_par_claimed_idx, start_idx)) {
-      // The current worker has successfully claimed the chunk [start_idx..end_idx)
-      end_idx = MIN2(end_idx, _n_hot);
-      for (int i = start_idx; i < end_idx; i++) {
-        jbyte* card_ptr = _hot_cache[i];
-        if (card_ptr != NULL) {
-          if (g1rs->refine_card(card_ptr, worker_i, true)) {
-            // The part of the heap spanned by the card contains references
-            // that point into the current collection set.
-            // We need to record the card pointer in the DirtyCardQueueSet
-            // that we use for such cards.
-            //
-            // The only time we care about recording cards that contain
-            // references that point into the collection set is during
-            // RSet updating while within an evacuation pause.
-            // In this case worker_i should be the id of a GC worker thread
-            assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
-            assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),
-                   err_msg("incorrect worker id: "UINT32_FORMAT, worker_i));
-
-            into_cset_dcq->enqueue(card_ptr);
-          }
+          into_cset_dcq->enqueue(card_ptr);
         }
+      } else {
+        break;
       }
     }
   }
+
   // The existing entries in the hot card cache, which were just refined
   // above, are discarded prior to re-enabling the cache near the end of the GC.
 }
--- a/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,21 +54,33 @@
 // code, increasing throughput.
 
 class G1HotCardCache: public CHeapObj<mtGC> {
-  G1CollectedHeap*   _g1h;
+
+  G1CollectedHeap*  _g1h;
+
+  bool              _use_cache;
+
+  G1CardCounts      _card_counts;
 
   // The card cache table
-  jbyte**      _hot_cache;
+  jbyte**           _hot_cache;
 
-  int          _hot_cache_size;
-  int          _n_hot;
-  int          _hot_cache_idx;
+  size_t            _hot_cache_size;
+
+  int               _hot_cache_par_chunk_size;
 
-  int          _hot_cache_par_chunk_size;
-  volatile int _hot_cache_par_claimed_idx;
+  // Avoids false sharing when concurrently updating _hot_cache_idx or
+  // _hot_cache_par_claimed_idx. These are never updated at the same time
+  // thus it's not necessary to separate them as well
+  char _pad_before[DEFAULT_CACHE_LINE_SIZE];
+
+  volatile size_t _hot_cache_idx;
 
-  bool         _use_cache;
+  volatile size_t _hot_cache_par_claimed_idx;
 
-  G1CardCounts _card_counts;
+  char _pad_after[DEFAULT_CACHE_LINE_SIZE];
+
+  // The number of cached cards a thread claims when flushing the cache
+  static const int ClaimChunkSize = 32;
 
   bool default_use_cache() const {
     return (G1ConcRSLogCacheSize > 0);
@@ -110,16 +122,25 @@
   void reset_hot_cache() {
     assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
     assert(Thread::current()->is_VM_thread(), "Current thread should be the VMthread");
-    _hot_cache_idx = 0; _n_hot = 0;
+    if (default_use_cache()) {
+        reset_hot_cache_internal();
+    }
   }
 
-  bool hot_cache_is_empty() { return _n_hot == 0; }
-
   // Zeros the values in the card counts table for entire committed heap
   void reset_card_counts();
 
   // Zeros the values in the card counts table for the given region
   void reset_card_counts(HeapRegion* hr);
+
+ private:
+  void reset_hot_cache_internal() {
+    assert(_hot_cache != NULL, "Logic");
+    _hot_cache_idx = 0;
+    for (size_t i = 0; i < _hot_cache_size; i++) {
+      _hot_cache[i] = NULL;
+    }
+  }
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1HOTCARDCACHE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/g1InCSetState.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP
+
+#include "gc_implementation/g1/g1BiasedArray.hpp"
+#include "memory/allocation.hpp"
+
+// Per-region state during garbage collection.
+struct InCSetState {
+ public:
+  // We use different types to represent the state value. Particularly SPARC puts
+  // values in structs from "left to right", i.e. MSB to LSB. This results in many
+  // unnecessary shift operations when loading and storing values of this type.
+  // This degrades performance significantly (>10%) on that platform.
+  // Other tested ABIs do not seem to have this problem, and actually tend to
+  // favor smaller types, so we use the smallest usable type there.
+#ifdef SPARC
+  #define CSETSTATE_FORMAT INTPTR_FORMAT
+  typedef intptr_t in_cset_state_t;
+#else
+  #define CSETSTATE_FORMAT "%d"
+  typedef int8_t in_cset_state_t;
+#endif
+ private:
+  in_cset_state_t _value;
+ public:
+  enum {
+    // Selection of the values were driven to micro-optimize the encoding and
+    // frequency of the checks.
+    // The most common check is whether the region is in the collection set or not.
+    // This encoding allows us to use an != 0 check which in some architectures
+    // (x86*) can be encoded slightly more efficently than a normal comparison
+    // against zero.
+    // The same situation occurs when checking whether the region is humongous
+    // or not, which is encoded by values < 0.
+    // The other values are simply encoded in increasing generation order, which
+    // makes getting the next generation fast by a simple increment.
+    Humongous    = -1,    // The region is humongous - note that actually any value < 0 would be possible here.
+    NotInCSet    =  0,    // The region is not in the collection set.
+    Young        =  1,    // The region is in the collection set and a young region.
+    Old          =  2,    // The region is in the collection set and an old region.
+    Num
+  };
+
+  InCSetState(in_cset_state_t value = NotInCSet) : _value(value) {
+    assert(is_valid(), err_msg("Invalid state %d", _value));
+  }
+
+  in_cset_state_t value() const        { return _value; }
+
+  void set_old()                       { _value = Old; }
+
+  bool is_in_cset_or_humongous() const { return _value != NotInCSet; }
+  bool is_in_cset() const              { return _value > NotInCSet; }
+  bool is_humongous() const            { return _value < NotInCSet; }
+  bool is_young() const                { return _value == Young; }
+  bool is_old() const                  { return _value == Old; }
+
+#ifdef ASSERT
+  bool is_default() const              { return !is_in_cset_or_humongous(); }
+  bool is_valid() const                { return (_value >= Humongous) && (_value < Num); }
+  bool is_valid_gen() const            { return (_value >= Young && _value <= Old); }
+#endif
+};
+
+// Instances of this class are used for quick tests on whether a reference points
+// into the collection set and into which generation or is a humongous object
+//
+// Each of the array's elements indicates whether the corresponding region is in
+// the collection set and if so in which generation, or a humongous region.
+//
+// We use this to speed up reference processing during young collection and
+// quickly reclaim humongous objects. For the latter, by making a humongous region
+// succeed this test, we sort-of add it to the collection set. During the reference
+// iteration closures, when we see a humongous region, we then simply mark it as
+// referenced, i.e. live.
+class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray<InCSetState> {
+ protected:
+  InCSetState default_value() const { return InCSetState::NotInCSet; }
+ public:
+  void set_humongous(uintptr_t index) {
+    assert(get_by_index(index).is_default(),
+           err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
+    set_by_index(index, InCSetState::Humongous);
+  }
+
+  void clear_humongous(uintptr_t index) {
+    set_by_index(index, InCSetState::NotInCSet);
+  }
+
+  void set_in_young(uintptr_t index) {
+    assert(get_by_index(index).is_default(),
+           err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
+    set_by_index(index, InCSetState::Young);
+  }
+
+  void set_in_old(uintptr_t index) {
+    assert(get_by_index(index).is_default(),
+           err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
+    set_by_index(index, InCSetState::Old);
+  }
+
+  bool is_in_cset_or_humongous(HeapWord* addr) const { return at(addr).is_in_cset_or_humongous(); }
+  bool is_in_cset(HeapWord* addr) const { return at(addr).is_in_cset(); }
+  InCSetState at(HeapWord* addr) const { return get_by_address(addr); }
+  void clear() { G1BiasedMappedArray<InCSetState>::clear(); }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP
--- a/src/share/vm/gc_implementation/g1/g1Log.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1Log.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -28,6 +28,7 @@
 #include "memory/allocation.hpp"
 
 class G1Log : public AllStatic {
+ public:
   typedef enum {
     LevelNone,
     LevelFine,
@@ -35,6 +36,7 @@
     LevelFinest
   } LogLevel;
 
+ private:
   static LogLevel _level;
 
  public:
@@ -50,6 +52,10 @@
     return _level == LevelFinest;
   }
 
+  static LogLevel level() {
+    return _level;
+  }
+
   static void init();
 };
 
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -31,6 +31,7 @@
 #include "code/icBuffer.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
+#include "gc_implementation/g1/g1RootProcessor.hpp"
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/shared/gcHeapSummary.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
@@ -126,21 +127,22 @@
   GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace(" 1");
 
-  SharedHeap* sh = SharedHeap::heap();
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
   // Need cleared claim bits for the roots processing
   ClassLoaderDataGraph::clear_claimed_marks();
 
   MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::follow_root_closure, !CodeBlobToOopClosure::FixRelocations);
-  sh->process_strong_roots(true,   // activate StrongRootsScope
-                           SharedHeap::SO_None,
-                           &GenMarkSweep::follow_root_closure,
-                           &GenMarkSweep::follow_cld_closure,
-                           &follow_code_closure);
+  {
+    G1RootProcessor root_processor(g1h);
+    root_processor.process_strong_roots(&GenMarkSweep::follow_root_closure,
+                                        &GenMarkSweep::follow_cld_closure,
+                                        &follow_code_closure);
+  }
 
   // Process reference objects found during marking
   ReferenceProcessor* rp = GenMarkSweep::ref_processor();
-  assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Sanity");
+  assert(rp == g1h->ref_processor_stw(), "Sanity");
 
   rp->setup_policy(clear_all_softrefs);
   const ReferenceProcessorStats& stats =
@@ -226,6 +228,12 @@
   }
 };
 
+class G1AlwaysTrueClosure: public BoolObjectClosure {
+public:
+  bool do_object_b(oop p) { return true; }
+};
+static G1AlwaysTrueClosure always_true;
+
 void G1MarkSweep::mark_sweep_phase3() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
@@ -233,24 +241,23 @@
   GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace("3");
 
-  SharedHeap* sh = SharedHeap::heap();
-
   // Need cleared claim bits for the roots processing
   ClassLoaderDataGraph::clear_claimed_marks();
 
   CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations);
-  sh->process_all_roots(true,  // activate StrongRootsScope
-                        SharedHeap::SO_AllCodeCache,
-                        &GenMarkSweep::adjust_pointer_closure,
-                        &GenMarkSweep::adjust_cld_closure,
-                        &adjust_code_closure);
+  {
+    G1RootProcessor root_processor(g1h);
+    root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
+                                     &GenMarkSweep::adjust_cld_closure,
+                                     &adjust_code_closure);
+  }
 
   assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity");
   g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
-  sh->process_weak_roots(&GenMarkSweep::adjust_pointer_closure);
+  JNIHandles::weak_oops_do(&always_true, &GenMarkSweep::adjust_pointer_closure);
 
   if (G1StringDedup::is_enabled()) {
     G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
--- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP
 
 #include "memory/iterator.hpp"
+#include "oops/markOop.hpp"
 
 class HeapRegion;
 class G1CollectedHeap;
@@ -239,14 +240,14 @@
   G1CollectedHeap* _g1;
   G1RemSet* _g1_rem_set;
   HeapRegion* _from;
-  OopsInHeapRegionClosure* _push_ref_cl;
+  G1ParPushHeapRSClosure* _push_ref_cl;
   bool _record_refs_into_cset;
   uint _worker_i;
 
 public:
   G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
                                 G1RemSet* rs,
-                                OopsInHeapRegionClosure* push_ref_cl,
+                                G1ParPushHeapRSClosure* push_ref_cl,
                                 bool record_refs_into_cset,
                                 uint worker_i = 0);
 
@@ -256,7 +257,8 @@
   }
 
   bool self_forwarded(oop obj) {
-    bool result = (obj->is_forwarded() && (obj->forwardee()== obj));
+    markOop m = obj->mark();
+    bool result = (m->is_marked() && ((oop)m->decode_pointer() == obj));
     return result;
   }
 
--- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -67,8 +67,8 @@
 
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj);
-    if (state == G1CollectedHeap::InCSet) {
+    const InCSetState state = _g1->in_cset_state(obj);
+    if (state.is_in_cset()) {
       // We're not going to even bother checking whether the object is
       // already forwarded or not, as this usually causes an immediate
       // stall. We'll try to prefetch the object (for write, given that
@@ -87,7 +87,7 @@
 
       _par_scan_state->push_on_queue(p);
     } else {
-      if (state == G1CollectedHeap::IsHumongous) {
+      if (state.is_humongous()) {
         _g1->set_humongous_is_live(obj);
       }
       _par_scan_state->update_rs(_from, p, _worker_id);
--- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -45,7 +45,8 @@
 #include "utilities/bitMap.inline.hpp"
 
 G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL),
-  _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) {
+  _high_boundary(NULL), _committed(), _page_size(0), _special(false),
+  _dirty(), _executable(false) {
 }
 
 bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
@@ -66,6 +67,9 @@
   assert(_committed.size() == 0, "virtual space initialized more than once");
   uintx size_in_bits = rs.size() / page_size;
   _committed.resize(size_in_bits, /* in_resource_area */ false);
+  if (_special) {
+    _dirty.resize(size_in_bits, /* in_resource_area */ false);
+  }
 
   return true;
 }
@@ -84,6 +88,7 @@
   _executable             = false;
   _page_size              = 0;
   _committed.resize(0, false);
+  _dirty.resize(0, false);
 }
 
 size_t G1PageBasedVirtualSpace::committed_size() const {
@@ -120,31 +125,40 @@
   return num * _page_size;
 }
 
-MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
+bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
   // We need to make sure to commit all pages covered by the given area.
   guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
 
-  if (!_special) {
+  bool zero_filled = true;
+  uintptr_t end = start + size_in_pages;
+
+  if (_special) {
+    // Check for dirty pages and update zero_filled if any found.
+    if (_dirty.get_next_one_offset(start,end) < end) {
+      zero_filled = false;
+      _dirty.clear_range(start, end);
+    }
+  } else {
     os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable,
                               err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
   }
-  _committed.set_range(start, start + size_in_pages);
+  _committed.set_range(start, end);
 
-  MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
-  return result;
+  return zero_filled;
 }
 
-MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
+void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
   guarantee(is_area_committed(start, size_in_pages), "checking");
 
-  if (!_special) {
+  if (_special) {
+    // Mark that memory is dirty. If committed again the memory might
+    // need to be cleared explicitly.
+    _dirty.set_range(start, start + size_in_pages);
+  } else {
     os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
   }
 
   _committed.clear_range(start, start + size_in_pages);
-
-  MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
-  return result;
 }
 
 bool G1PageBasedVirtualSpace::contains(const void* p) const {
@@ -154,7 +168,7 @@
 #ifndef PRODUCT
 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
   out->print   ("Virtual space:");
-  if (special()) out->print(" (pinned in memory)");
+  if (_special) out->print(" (pinned in memory)");
   out->cr();
   out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
   out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
--- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -49,6 +49,12 @@
   // Bitmap used for verification of commit/uncommit operations.
   BitMap _committed;
 
+  // Bitmap used to keep track of which pages are dirty or not for _special
+  // spaces. This is needed because for those spaces the underlying memory
+  // will only be zero filled the first time it is committed. Calls to commit
+  // will use this bitmap and return whether or not the memory is zero filled.
+  BitMap _dirty;
+
   // Indicates that the entire space has been committed and pinned in memory,
   // os::commit_memory() or os::uncommit_memory() have no function.
   bool _special;
@@ -71,12 +77,11 @@
  public:
 
   // Commit the given area of pages starting at start being size_in_pages large.
-  MemRegion commit(uintptr_t start, size_t size_in_pages);
+  // Returns true if the given area is zero filled upon completion.
+  bool commit(uintptr_t start, size_t size_in_pages);
 
   // Uncommit the given area of pages starting at start being size_in_pages large.
-  MemRegion uncommit(uintptr_t start, size_t size_in_pages);
-
-  bool special() const { return _special; }
+  void uncommit(uintptr_t start, size_t size_in_pages);
 
   // Initialization
   G1PageBasedVirtualSpace();
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -38,6 +38,7 @@
     _g1_rem(g1h->g1_rem_set()),
     _hash_seed(17), _queue_num(queue_num),
     _term_attempts(0),
+    _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
     _age_table(false), _scanner(g1h, rp),
     _strong_roots_time(0), _term_time(0) {
   _scanner.set_par_scan_thread_state(this);
@@ -59,6 +60,12 @@
 
   _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h);
 
+  _dest[InCSetState::NotInCSet]    = InCSetState::NotInCSet;
+  // The dest for Young is used when the objects are aged enough to
+  // need to be moved to the next space.
+  _dest[InCSetState::Young]        = InCSetState::Old;
+  _dest[InCSetState::Old]          = InCSetState::Old;
+
   _start = os::elapsedTime();
 }
 
@@ -150,86 +157,126 @@
   } while (!_refs->is_empty());
 }
 
-oop G1ParScanThreadState::copy_to_survivor_space(oop const old) {
-  size_t word_sz = old->size();
-  HeapRegion* from_region = _g1h->heap_region_containing_raw(old);
+HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state,
+                                                      InCSetState* dest,
+                                                      size_t word_sz,
+                                                      AllocationContext_t const context) {
+  assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: " CSETSTATE_FORMAT, state.value()));
+  assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
+
+  // Right now we only have two types of regions (young / old) so
+  // let's keep the logic here simple. We can generalize it when necessary.
+  if (dest->is_young()) {
+    HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old,
+                                                          word_sz, context);
+    if (obj_ptr == NULL) {
+      return NULL;
+    }
+    // Make sure that we won't attempt to copy any other objects out
+    // of a survivor region (given that apparently we cannot allocate
+    // any new ones) to avoid coming into this slow path.
+    _tenuring_threshold = 0;
+    dest->set_old();
+    return obj_ptr;
+  } else {
+    assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
+    // no other space to try.
+    return NULL;
+  }
+}
+
+InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) {
+  if (state.is_young()) {
+    age = !m->has_displaced_mark_helper() ? m->age()
+                                          : m->displaced_mark_helper()->age();
+    if (age < _tenuring_threshold) {
+      return state;
+    }
+  }
+  return dest(state);
+}
+
+oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
+                                                 oop const old,
+                                                 markOop const old_mark) {
+  const size_t word_sz = old->size();
+  HeapRegion* const from_region = _g1h->heap_region_containing_raw(old);
   // +1 to make the -1 indexes valid...
-  int       young_index = from_region->young_index_in_cset()+1;
+  const int young_index = from_region->young_index_in_cset()+1;
   assert( (from_region->is_young() && young_index >  0) ||
          (!from_region->is_young() && young_index == 0), "invariant" );
-  G1CollectorPolicy* g1p = _g1h->g1_policy();
-  markOop m = old->mark();
-  int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age()
-                                           : m->age();
-  GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age,
-                                                             word_sz);
-  AllocationContext_t context = from_region->allocation_context();
-  HeapWord* obj_ptr = _g1_par_allocator->allocate(alloc_purpose, word_sz, context);
+  const AllocationContext_t context = from_region->allocation_context();
+
+  uint age = 0;
+  InCSetState dest_state = next_state(state, old_mark, age);
+  HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context);
+
+  // PLAB allocations should succeed most of the time, so we'll
+  // normally check against NULL once and that's it.
+  if (obj_ptr == NULL) {
+    obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
+    if (obj_ptr == NULL) {
+      obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
+      if (obj_ptr == NULL) {
+        // This will either forward-to-self, or detect that someone else has
+        // installed a forwarding pointer.
+        return _g1h->handle_evacuation_failure_par(this, old);
+      }
+    }
+  }
+
+  assert(obj_ptr != NULL, "when we get here, allocation should have succeeded");
 #ifndef PRODUCT
   // Should this evacuation fail?
   if (_g1h->evacuation_should_fail()) {
-    if (obj_ptr != NULL) {
-      _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context);
-      obj_ptr = NULL;
-    }
+    // Doing this after all the allocation attempts also tests the
+    // undo_allocation() method too.
+    _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+    return _g1h->handle_evacuation_failure_par(this, old);
   }
 #endif // !PRODUCT
 
-  if (obj_ptr == NULL) {
-    // This will either forward-to-self, or detect that someone else has
-    // installed a forwarding pointer.
-    return _g1h->handle_evacuation_failure_par(this, old);
-  }
-
-  oop obj = oop(obj_ptr);
-
   // We're going to allocate linearly, so might as well prefetch ahead.
   Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
 
-  oop forward_ptr = old->forward_to_atomic(obj);
+  const oop obj = oop(obj_ptr);
+  const oop forward_ptr = old->forward_to_atomic(obj);
   if (forward_ptr == NULL) {
     Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
 
-    // alloc_purpose is just a hint to allocate() above, recheck the type of region
-    // we actually allocated from and update alloc_purpose accordingly
-    HeapRegion* to_region = _g1h->heap_region_containing_raw(obj_ptr);
-    alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured;
-
-    if (g1p->track_object_age(alloc_purpose)) {
-      // We could simply do obj->incr_age(). However, this causes a
-      // performance issue. obj->incr_age() will first check whether
-      // the object has a displaced mark by checking its mark word;
-      // getting the mark word from the new location of the object
-      // stalls. So, given that we already have the mark word and we
-      // are about to install it anyway, it's better to increase the
-      // age on the mark word, when the object does not have a
-      // displaced mark word. We're not expecting many objects to have
-      // a displaced marked word, so that case is not optimized
-      // further (it could be...) and we simply call obj->incr_age().
-
-      if (m->has_displaced_mark_helper()) {
-        // in this case, we have to install the mark word first,
+    if (dest_state.is_young()) {
+      if (age < markOopDesc::max_age) {
+        age++;
+      }
+      if (old_mark->has_displaced_mark_helper()) {
+        // In this case, we have to install the mark word first,
         // otherwise obj looks to be forwarded (the old mark word,
         // which contains the forward pointer, was copied)
-        obj->set_mark(m);
-        obj->incr_age();
+        obj->set_mark(old_mark);
+        markOop new_mark = old_mark->displaced_mark_helper()->set_age(age);
+        old_mark->set_displaced_mark_helper(new_mark);
       } else {
-        m = m->incr_age();
-        obj->set_mark(m);
+        obj->set_mark(old_mark->set_age(age));
       }
-      age_table()->add(obj, word_sz);
+      age_table()->add(age, word_sz);
     } else {
-      obj->set_mark(m);
+      obj->set_mark(old_mark);
     }
 
     if (G1StringDedup::is_enabled()) {
-      G1StringDedup::enqueue_from_evacuation(from_region->is_young(),
-                                             to_region->is_young(),
+      const bool is_from_young = state.is_young();
+      const bool is_to_young = dest_state.is_young();
+      assert(is_from_young == _g1h->heap_region_containing_raw(old)->is_young(),
+             "sanity");
+      assert(is_to_young == _g1h->heap_region_containing_raw(obj)->is_young(),
+             "sanity");
+      G1StringDedup::enqueue_from_evacuation(is_from_young,
+                                             is_to_young,
                                              queue_num(),
                                              obj);
     }
 
-    size_t* surv_young_words = surviving_young_words();
+    size_t* const surv_young_words = surviving_young_words();
     surv_young_words[young_index] += word_sz;
 
     if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
@@ -240,14 +287,13 @@
       oop* old_p = set_partial_array_mask(old);
       push_on_queue(old_p);
     } else {
-      // No point in using the slower heap_region_containing() method,
-      // given that we know obj is in the heap.
-      _scanner.set_region(_g1h->heap_region_containing_raw(obj));
+      HeapRegion* const to_region = _g1h->heap_region_containing_raw(obj_ptr);
+      _scanner.set_region(to_region);
       obj->oop_iterate_backwards(&_scanner);
     }
+    return obj;
   } else {
-    _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context);
-    obj = forward_ptr;
+    _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+    return forward_ptr;
   }
-  return obj;
 }
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -46,14 +46,16 @@
   G1SATBCardTableModRefBS* _ct_bs;
   G1RemSet* _g1_rem;
 
-  G1ParGCAllocator*   _g1_par_allocator;
-
-  ageTable            _age_table;
+  G1ParGCAllocator* _g1_par_allocator;
 
-  G1ParScanClosure    _scanner;
+  ageTable          _age_table;
+  InCSetState       _dest[InCSetState::Num];
+  // Local tenuring threshold.
+  uint              _tenuring_threshold;
+  G1ParScanClosure  _scanner;
 
-  size_t           _alloc_buffer_waste;
-  size_t           _undo_waste;
+  size_t            _alloc_buffer_waste;
+  size_t            _undo_waste;
 
   OopsInHeapRegionClosure*      _evac_failure_cl;
 
@@ -82,6 +84,14 @@
   DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
   G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
 
+  InCSetState dest(InCSetState original) const {
+    assert(original.is_valid(),
+           err_msg("Original state invalid: " CSETSTATE_FORMAT, original.value()));
+    assert(_dest[original.value()].is_valid_gen(),
+           err_msg("Dest state is invalid: " CSETSTATE_FORMAT, _dest[original.value()].value()));
+    return _dest[original.value()];
+  }
+
  public:
   G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
   ~G1ParScanThreadState();
@@ -112,7 +122,6 @@
       }
    }
   }
- public:
 
   void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
     _evac_failure_cl = evac_failure_cl;
@@ -193,9 +202,20 @@
   template <class T> inline void deal_with_reference(T* ref_to_scan);
 
   inline void dispatch_reference(StarTask ref);
+
+  // Tries to allocate word_sz in the PLAB of the next "generation" after trying to
+  // allocate into dest. State is the original (source) cset state for the object
+  // that is allocated for.
+  // Returns a non-NULL pointer if successful, and updates dest if required.
+  HeapWord* allocate_in_next_plab(InCSetState const state,
+                                  InCSetState* dest,
+                                  size_t word_sz,
+                                  AllocationContext_t const context);
+
+  inline InCSetState next_state(InCSetState const state, markOop const m, uint& age);
  public:
 
-  oop copy_to_survivor_space(oop const obj);
+  oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark);
 
   void trim_queue();
 
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -38,20 +38,21 @@
   // set, due to (benign) races in the claim mechanism during RSet scanning more
   // than one thread might claim the same card. So the same card may be
   // processed multiple times. So redo this check.
-  G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj);
-  if (in_cset_state == G1CollectedHeap::InCSet) {
+  const InCSetState in_cset_state = _g1h->in_cset_state(obj);
+  if (in_cset_state.is_in_cset()) {
     oop forwardee;
-    if (obj->is_forwarded()) {
-      forwardee = obj->forwardee();
+    markOop m = obj->mark();
+    if (m->is_marked()) {
+      forwardee = (oop) m->decode_pointer();
     } else {
-      forwardee = copy_to_survivor_space(obj);
+      forwardee = copy_to_survivor_space(in_cset_state, obj, m);
     }
     oopDesc::encode_store_heap_oop(p, forwardee);
-  } else if (in_cset_state == G1CollectedHeap::IsHumongous) {
+  } else if (in_cset_state.is_humongous()) {
     _g1h->set_humongous_is_live(obj);
   } else {
-    assert(in_cset_state == G1CollectedHeap::InNeither,
-           err_msg("In_cset_state must be InNeither here, but is %d", in_cset_state));
+    assert(!in_cset_state.is_in_cset_or_humongous(),
+           err_msg("In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value()));
   }
 
   assert(obj != NULL, "Must be");
--- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -67,9 +67,9 @@
   }
 
   virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
-    _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
+    bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
     _commit_map.set_range(start_idx, start_idx + num_regions);
-    fire_on_commit(start_idx, num_regions, true);
+    fire_on_commit(start_idx, num_regions, zero_filled);
   }
 
   virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
@@ -117,8 +117,7 @@
       uint old_refcount = _refcounts.get_by_index(idx);
       bool zero_filled = false;
       if (old_refcount == 0) {
-        _storage.commit(idx, 1);
-        zero_filled = true;
+        zero_filled = _storage.commit(idx, 1);
       }
       _refcounts.set_by_index(idx, old_refcount + 1);
       _commit_map.set_bit(i);
--- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -78,9 +78,8 @@
     _cards_scanned(NULL), _total_cards_scanned(0),
     _prev_period_summary()
 {
-  _seq_task = new SubTasksDone(NumSeqTasks);
   guarantee(n_workers() > 0, "There should be some workers");
-  _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC);
+  _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
   for (uint i = 0; i < n_workers(); i++) {
     _cset_rs_update_cl[i] = NULL;
   }
@@ -90,11 +89,10 @@
 }
 
 G1RemSet::~G1RemSet() {
-  delete _seq_task;
   for (uint i = 0; i < n_workers(); i++) {
     assert(_cset_rs_update_cl[i] == NULL, "it should be");
   }
-  FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl, mtGC);
+  FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl, mtGC);
 }
 
 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
@@ -108,7 +106,7 @@
   size_t _cards_done, _cards;
   G1CollectedHeap* _g1h;
 
-  OopsInHeapRegionClosure* _oc;
+  G1ParPushHeapRSClosure* _oc;
   CodeBlobClosure* _code_root_cl;
 
   G1BlockOffsetSharedArray* _bot_shared;
@@ -120,7 +118,7 @@
   bool   _try_claimed;
 
 public:
-  ScanRSClosure(OopsInHeapRegionClosure* oc,
+  ScanRSClosure(G1ParPushHeapRSClosure* oc,
                 CodeBlobClosure* code_root_cl,
                 uint worker_i) :
     _oc(oc),
@@ -142,16 +140,13 @@
   void scanCard(size_t index, HeapRegion *r) {
     // Stack allocate the DirtyCardToOopClosure instance
     HeapRegionDCTOC cl(_g1h, r, _oc,
-                       CardTableModRefBS::Precise,
-                       HeapRegionDCTOC::IntoCSFilterKind);
+                       CardTableModRefBS::Precise);
 
     // Set the "from" region in the closure.
     _oc->set_region(r);
-    HeapWord* card_start = _bot_shared->address_for_index(index);
-    HeapWord* card_end = card_start + G1BlockOffsetSharedArray::N_words;
-    Space *sp = SharedHeap::heap()->space_containing(card_start);
-    MemRegion sm_region = sp->used_region_at_save_marks();
-    MemRegion mr = sm_region.intersection(MemRegion(card_start,card_end));
+    MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
+    MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
+    MemRegion mr = pre_gc_allocated.intersection(card_region);
     if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
       // We make the card as "claimed" lazily (so races are possible
       // but they're benign), which reduces the number of duplicate
@@ -240,7 +235,7 @@
   size_t cards_looked_up() { return _cards;}
 };
 
-void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
+void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
                       CodeBlobClosure* code_root_cl,
                       uint worker_i) {
   double rs_time_start = os::elapsedTime();
@@ -258,9 +253,8 @@
   assert(_cards_scanned != NULL, "invariant");
   _cards_scanned[worker_i] = scanRScl.cards_done();
 
-  _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
-  _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
-                                                         scanRScl.strong_code_root_scan_time_sec() * 1000.0);
+  _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
+  _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec());
 }
 
 // Closure used for updating RSets and recording references that
@@ -297,29 +291,18 @@
 };
 
 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
-  double start = os::elapsedTime();
+  G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
   // Apply the given closure to all remaining log entries.
   RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
 
   _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
-
-  // Now there should be no dirty cards.
-  if (G1RSLogCheckCardTable) {
-    CountNonCleanMemRegionClosure cl(_g1);
-    _ct_bs->mod_card_iterate(&cl);
-    // XXX This isn't true any more: keeping cards of young regions
-    // marked dirty broke it.  Need some reasonable fix.
-    guarantee(cl.n() == 0, "Card table should be clean.");
-  }
-
-  _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
 }
 
 void G1RemSet::cleanupHRRS() {
   HeapRegionRemSet::cleanup();
 }
 
-void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
+void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
                                            CodeBlobClosure* code_root_cl,
                                            uint worker_i) {
 #if CARD_REPEAT_HISTO
@@ -344,23 +327,8 @@
 
   assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
 
-  // The two flags below were introduced temporarily to serialize
-  // the updating and scanning of remembered sets. There are some
-  // race conditions when these two operations are done in parallel
-  // and they are causing failures. When we resolve said race
-  // conditions, we'll revert back to parallel remembered set
-  // updating and scanning. See CRs 6677707 and 6677708.
-  if (G1UseParallelRSetUpdating || (worker_i == 0)) {
-    updateRS(&into_cset_dcq, worker_i);
-  } else {
-    _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0);
-    _g1p->phase_times()->record_update_rs_time(worker_i, 0.0);
-  }
-  if (G1UseParallelRSetScanning || (worker_i == 0)) {
-    scanRS(oc, code_root_cl, worker_i);
-  } else {
-    _g1p->phase_times()->record_scan_rs_time(worker_i, 0.0);
-  }
+  updateRS(&into_cset_dcq, worker_i);
+  scanRS(oc, code_root_cl, worker_i);
 
   // We now clear the cached values of _cset_rs_update_cl for this worker
   _cset_rs_update_cl[worker_i] = NULL;
@@ -461,7 +429,7 @@
 G1UpdateRSOrPushRefOopClosure::
 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
                               G1RemSet* rs,
-                              OopsInHeapRegionClosure* push_ref_cl,
+                              G1ParPushHeapRSClosure* push_ref_cl,
                               bool record_refs_into_cset,
                               uint worker_i) :
   _g1(g1h), _g1_rem_set(rs), _from(NULL),
@@ -562,7 +530,7 @@
   ct_freq_note_card(_ct_bs->index_for(start));
 #endif
 
-  OopsInHeapRegionClosure* oops_in_heap_closure = NULL;
+  G1ParPushHeapRSClosure* oops_in_heap_closure = NULL;
   if (check_for_refs_into_cset) {
     // ConcurrentG1RefineThreads have worker numbers larger than what
     // _cset_rs_update_cl[] is set up to handle. But those threads should
--- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -33,6 +33,7 @@
 class G1CollectedHeap;
 class CardTableModRefBarrierSet;
 class ConcurrentG1Refine;
+class G1ParPushHeapRSClosure;
 
 // A G1RemSet in which each heap region has a rem set that records the
 // external heap references into it.  Uses a mod ref bs to track updates,
@@ -58,7 +59,6 @@
   };
 
   CardTableModRefBS*     _ct_bs;
-  SubTasksDone*          _seq_task;
   G1CollectorPolicy*     _g1p;
 
   ConcurrentG1Refine*    _cg1r;
@@ -68,7 +68,7 @@
 
   // Used for caching the closure that is responsible for scanning
   // references into the collection set.
-  OopsInHeapRegionClosure** _cset_rs_update_cl;
+  G1ParPushHeapRSClosure** _cset_rs_update_cl;
 
   // Print the given summary info
   virtual void print_summary_info(G1RemSetSummary * summary, const char * header = NULL);
@@ -95,7 +95,7 @@
   // partitioning the work to be done. It should be the same as
   // the "i" passed to the calling thread's work(i) function.
   // In the sequential case this param will be ignored.
-  void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
+  void oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
                                    CodeBlobClosure* code_root_cl,
                                    uint worker_i);
 
@@ -107,7 +107,7 @@
   void prepare_for_oops_into_collection_set_do();
   void cleanup_after_oops_into_collection_set_do();
 
-  void scanRS(OopsInHeapRegionClosure* oc,
+  void scanRS(G1ParPushHeapRSClosure* oc,
               CodeBlobClosure* code_root_cl,
               uint worker_i);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "code/codeCache.hpp"
+#include "gc_implementation/g1/bufferingOopClosure.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
+#include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "gc_implementation/g1/g1RootProcessor.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/fprofiler.hpp"
+#include "runtime/mutex.hpp"
+#include "services/management.hpp"
+
+class G1CodeBlobClosure : public CodeBlobClosure {
+  class HeapRegionGatheringOopClosure : public OopClosure {
+    G1CollectedHeap* _g1h;
+    OopClosure* _work;
+    nmethod* _nm;
+
+    template <typename T>
+    void do_oop_work(T* p) {
+      _work->do_oop(p);
+      T oop_or_narrowoop = oopDesc::load_heap_oop(p);
+      if (!oopDesc::is_null(oop_or_narrowoop)) {
+        oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
+        HeapRegion* hr = _g1h->heap_region_containing_raw(o);
+        assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
+        hr->add_strong_code_root(_nm);
+      }
+    }
+
+  public:
+    HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
+
+    void do_oop(oop* o) {
+      do_oop_work(o);
+    }
+
+    void do_oop(narrowOop* o) {
+      do_oop_work(o);
+    }
+
+    void set_nm(nmethod* nm) {
+      _nm = nm;
+    }
+  };
+
+  HeapRegionGatheringOopClosure _oc;
+public:
+  G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
+
+  void do_code_blob(CodeBlob* cb) {
+    nmethod* nm = cb->as_nmethod_or_null();
+    if (nm != NULL) {
+      if (!nm->test_set_oops_do_mark()) {
+        _oc.set_nm(nm);
+        nm->oops_do(&_oc);
+        nm->fix_oop_relocations();
+      }
+    }
+  }
+};
+
+
+void G1RootProcessor::worker_has_discovered_all_strong_classes() {
+  uint n_workers = _g1h->n_par_threads();
+  assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
+
+  if (n_workers > 0) {
+    uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
+    if (new_value == n_workers) {
+      // This thread is last. Notify the others.
+      MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
+      _lock.notify_all();
+    }
+  }
+}
+
+void G1RootProcessor::wait_until_all_strong_classes_discovered() {
+  uint n_workers = _g1h->n_par_threads();
+  assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
+
+  if (n_workers > 0 && (uint)_n_workers_discovered_strong_classes != n_workers) {
+    MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
+    while ((uint)_n_workers_discovered_strong_classes != n_workers) {
+      _lock.wait(Mutex::_no_safepoint_check_flag, 0, false);
+    }
+  }
+}
+
+G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h) :
+    _g1h(g1h),
+    _process_strong_tasks(new SubTasksDone(G1RP_PS_NumElements)),
+    _srs(g1h),
+    _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false),
+    _n_workers_discovered_strong_classes(0) {}
+
+void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
+                                     OopClosure* scan_non_heap_weak_roots,
+                                     CLDClosure* scan_strong_clds,
+                                     CLDClosure* scan_weak_clds,
+                                     bool trace_metadata,
+                                     uint worker_i) {
+  // First scan the shared roots.
+  double ext_roots_start = os::elapsedTime();
+  G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
+
+  BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
+  BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
+
+  OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots;
+  OopClosure* const strong_roots = &buf_scan_non_heap_roots;
+
+  // CodeBlobClosures are not interoperable with BufferingOopClosures
+  G1CodeBlobClosure root_code_blobs(scan_non_heap_roots);
+
+  process_java_roots(strong_roots,
+                     trace_metadata ? scan_strong_clds : NULL,
+                     scan_strong_clds,
+                     trace_metadata ? NULL : scan_weak_clds,
+                     &root_code_blobs,
+                     phase_times,
+                     worker_i);
+
+  // This is the point where this worker thread will not find more strong CLDs/nmethods.
+  // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
+  if (trace_metadata) {
+    worker_has_discovered_all_strong_classes();
+  }
+
+  process_vm_roots(strong_roots, weak_roots, phase_times, worker_i);
+
+  {
+    // Now the CM ref_processor roots.
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) {
+      // We need to treat the discovered reference lists of the
+      // concurrent mark ref processor as roots and keep entries
+      // (which are added by the marking threads) on them live
+      // until they can be processed at the end of marking.
+      _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
+    }
+  }
+
+  if (trace_metadata) {
+    {
+      G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
+      // Barrier to make sure all workers passed
+      // the strong CLD and strong nmethods phases.
+      wait_until_all_strong_classes_discovered();
+    }
+
+    // Now take the complement of the strong CLDs.
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
+    ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
+  } else {
+    phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0);
+    phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0);
+  }
+
+  // Finish up any enqueued closure apps (attributed as object copy time).
+  buf_scan_non_heap_roots.done();
+  buf_scan_non_heap_weak_roots.done();
+
+  double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
+      + buf_scan_non_heap_weak_roots.closure_app_seconds();
+
+  phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec);
+
+  double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec;
+
+  phase_times->record_time_secs(G1GCPhaseTimes::ExtRootScan, worker_i, ext_root_time_sec);
+
+  // During conc marking we have to filter the per-thread SATB buffers
+  // to make sure we remove any oops into the CSet (which will show up
+  // as implicitly live).
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->mark_in_progress()) {
+      JavaThread::satb_mark_queue_set().filter_thread_buffers();
+    }
+  }
+
+  _process_strong_tasks->all_tasks_completed();
+}
+
+void G1RootProcessor::process_strong_roots(OopClosure* oops,
+                                           CLDClosure* clds,
+                                           CodeBlobClosure* blobs) {
+
+  process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
+  process_vm_roots(oops, NULL, NULL, 0);
+
+  _process_strong_tasks->all_tasks_completed();
+}
+
+void G1RootProcessor::process_all_roots(OopClosure* oops,
+                                        CLDClosure* clds,
+                                        CodeBlobClosure* blobs) {
+
+  process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0);
+  process_vm_roots(oops, oops, NULL, 0);
+
+  if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) {
+    CodeCache::blobs_do(blobs);
+  }
+
+  _process_strong_tasks->all_tasks_completed();
+}
+
+void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
+                                         CLDClosure* thread_stack_clds,
+                                         CLDClosure* strong_clds,
+                                         CLDClosure* weak_clds,
+                                         CodeBlobClosure* strong_code,
+                                         G1GCPhaseTimes* phase_times,
+                                         uint worker_i) {
+  assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set");
+  // Iterating over the CLDG and the Threads are done early to allow us to
+  // first process the strong CLDs and nmethods and then, after a barrier,
+  // let the thread process the weak CLDs and nmethods.
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
+      ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
+    Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code);
+  }
+}
+
+void G1RootProcessor::process_vm_roots(OopClosure* strong_roots,
+                                       OopClosure* weak_roots,
+                                       G1GCPhaseTimes* phase_times,
+                                       uint worker_i) {
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) {
+      Universe::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) {
+      JNIHandles::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_i);
+    if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) {
+      ObjectSynchronizer::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::FlatProfilerRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) {
+      FlatProfiler::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ManagementRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) {
+      Management::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMTIRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) {
+      JvmtiExport::oops_do(strong_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) {
+      SystemDictionary::roots_oops_do(strong_roots, weak_roots);
+    }
+  }
+
+  {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i);
+    // All threads execute the following. A specific chunk of buckets
+    // from the StringTable are the individual tasks.
+    if (weak_roots != NULL) {
+      StringTable::possibly_parallel_oops_do(weak_roots);
+    }
+  }
+}
+
+void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
+                                           OopClosure* scan_non_heap_weak_roots,
+                                           uint worker_i) {
+  G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
+  G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CodeCacheRoots, worker_i);
+
+  // Now scan the complement of the collection set.
+  G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
+
+  _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
+}
+
+void G1RootProcessor::set_num_workers(int active_workers) {
+  _process_strong_tasks->set_n_threads(active_workers);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/sharedHeap.hpp"
+#include "runtime/mutex.hpp"
+
+class CLDClosure;
+class CodeBlobClosure;
+class G1CollectedHeap;
+class G1GCPhaseTimes;
+class G1ParPushHeapRSClosure;
+class Monitor;
+class OopClosure;
+class SubTasksDone;
+
+// Scoped object to assist in applying oop, CLD and code blob closures to
+// root locations. Handles claiming of different root scanning tasks
+// and takes care of global state for root scanning via a StrongRootsScope.
+// In the parallel case there is a shared G1RootProcessor object where all
+// worker thread call the process_roots methods.
+class G1RootProcessor : public StackObj {
+  G1CollectedHeap* _g1h;
+  SubTasksDone* _process_strong_tasks;
+  SharedHeap::StrongRootsScope _srs;
+
+  // Used to implement the Thread work barrier.
+  Monitor _lock;
+  volatile jint _n_workers_discovered_strong_classes;
+
+  enum G1H_process_roots_tasks {
+    G1RP_PS_Universe_oops_do,
+    G1RP_PS_JNIHandles_oops_do,
+    G1RP_PS_ObjectSynchronizer_oops_do,
+    G1RP_PS_FlatProfiler_oops_do,
+    G1RP_PS_Management_oops_do,
+    G1RP_PS_SystemDictionary_oops_do,
+    G1RP_PS_ClassLoaderDataGraph_oops_do,
+    G1RP_PS_jvmti_oops_do,
+    G1RP_PS_CodeCache_oops_do,
+    G1RP_PS_filter_satb_buffers,
+    G1RP_PS_refProcessor_oops_do,
+    // Leave this one last.
+    G1RP_PS_NumElements
+  };
+
+  void worker_has_discovered_all_strong_classes();
+  void wait_until_all_strong_classes_discovered();
+
+  void process_java_roots(OopClosure* scan_non_heap_roots,
+                          CLDClosure* thread_stack_clds,
+                          CLDClosure* scan_strong_clds,
+                          CLDClosure* scan_weak_clds,
+                          CodeBlobClosure* scan_strong_code,
+                          G1GCPhaseTimes* phase_times,
+                          uint worker_i);
+
+  void process_vm_roots(OopClosure* scan_non_heap_roots,
+                        OopClosure* scan_non_heap_weak_roots,
+                        G1GCPhaseTimes* phase_times,
+                        uint worker_i);
+
+public:
+  G1RootProcessor(G1CollectedHeap* g1h);
+
+  // Apply closures to the strongly and weakly reachable roots in the system
+  // in a single pass.
+  // Record and report timing measurements for sub phases using the worker_i
+  void evacuate_roots(OopClosure* scan_non_heap_roots,
+                      OopClosure* scan_non_heap_weak_roots,
+                      CLDClosure* scan_strong_clds,
+                      CLDClosure* scan_weak_clds,
+                      bool trace_metadata,
+                      uint worker_i);
+
+  // Apply oops, clds and blobs to all strongly reachable roots in the system
+  void process_strong_roots(OopClosure* oops,
+                            CLDClosure* clds,
+                            CodeBlobClosure* blobs);
+
+  // Apply oops, clds and blobs to strongly and weakly reachable roots in the system
+  void process_all_roots(OopClosure* oops,
+                         CLDClosure* clds,
+                         CodeBlobClosure* blobs);
+
+  // Apply scan_rs to all locations in the union of the remembered sets for all
+  // regions in the collection set
+  // (having done "set_region" to indicate the region in which the root resides),
+  void scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
+                            OopClosure* scan_non_heap_weak_roots,
+                            uint worker_i);
+
+  // Inform the root processor about the number of worker threads
+  void set_num_workers(int active_workers);
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
--- a/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -105,7 +105,7 @@
 
 void G1StringDedup::oops_do(OopClosure* keep_alive) {
   assert(is_enabled(), "String deduplication not enabled");
-  unlink_or_oops_do(NULL, keep_alive);
+  unlink_or_oops_do(NULL, keep_alive, true /* allow_resize_and_rehash */);
 }
 
 void G1StringDedup::unlink(BoolObjectClosure* is_alive) {
@@ -122,37 +122,35 @@
 class G1StringDedupUnlinkOrOopsDoTask : public AbstractGangTask {
 private:
   G1StringDedupUnlinkOrOopsDoClosure _cl;
+  G1GCPhaseTimes* _phase_times;
 
 public:
   G1StringDedupUnlinkOrOopsDoTask(BoolObjectClosure* is_alive,
                                   OopClosure* keep_alive,
-                                  bool allow_resize_and_rehash) :
+                                  bool allow_resize_and_rehash,
+                                  G1GCPhaseTimes* phase_times) :
     AbstractGangTask("G1StringDedupUnlinkOrOopsDoTask"),
-    _cl(is_alive, keep_alive, allow_resize_and_rehash) {
-  }
+    _cl(is_alive, keep_alive, allow_resize_and_rehash), _phase_times(phase_times) { }
 
   virtual void work(uint worker_id) {
-    double queue_fixup_start = os::elapsedTime();
-    G1StringDedupQueue::unlink_or_oops_do(&_cl);
-
-    double table_fixup_start = os::elapsedTime();
-    G1StringDedupTable::unlink_or_oops_do(&_cl, worker_id);
-
-    double queue_fixup_time_ms = (table_fixup_start - queue_fixup_start) * 1000.0;
-    double table_fixup_time_ms = (os::elapsedTime() - table_fixup_start) * 1000.0;
-    G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
-    g1p->phase_times()->record_string_dedup_queue_fixup_worker_time(worker_id, queue_fixup_time_ms);
-    g1p->phase_times()->record_string_dedup_table_fixup_worker_time(worker_id, table_fixup_time_ms);
+    {
+      G1GCParPhaseTimesTracker x(_phase_times, G1GCPhaseTimes::StringDedupQueueFixup, worker_id);
+      G1StringDedupQueue::unlink_or_oops_do(&_cl);
+    }
+    {
+      G1GCParPhaseTimesTracker x(_phase_times, G1GCPhaseTimes::StringDedupTableFixup, worker_id);
+      G1StringDedupTable::unlink_or_oops_do(&_cl, worker_id);
+    }
   }
 };
 
-void G1StringDedup::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, bool allow_resize_and_rehash) {
+void G1StringDedup::unlink_or_oops_do(BoolObjectClosure* is_alive,
+                                      OopClosure* keep_alive,
+                                      bool allow_resize_and_rehash,
+                                      G1GCPhaseTimes* phase_times) {
   assert(is_enabled(), "String deduplication not enabled");
-  G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
-  g1p->phase_times()->note_string_dedup_fixup_start();
-  double fixup_start = os::elapsedTime();
 
-  G1StringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash);
+  G1StringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash, phase_times);
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
     g1h->set_par_threads();
@@ -161,10 +159,6 @@
   } else {
     task.work(0);
   }
-
-  double fixup_time_ms = (os::elapsedTime() - fixup_start) * 1000.0;
-  g1p->phase_times()->record_string_dedup_fixup_time(fixup_time_ms);
-  g1p->phase_times()->note_string_dedup_fixup_end();
 }
 
 void G1StringDedup::threads_do(ThreadClosure* tc) {
--- a/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -90,6 +90,7 @@
 class ThreadClosure;
 class outputStream;
 class G1StringDedupTable;
+class G1GCPhaseTimes;
 
 //
 // Main interface for interacting with string deduplication.
@@ -130,7 +131,7 @@
   static void oops_do(OopClosure* keep_alive);
   static void unlink(BoolObjectClosure* is_alive);
   static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive,
-                                bool allow_resize_and_rehash = true);
+                                bool allow_resize_and_rehash, G1GCPhaseTimes* phase_times = NULL);
 
   static void threads_do(ThreadClosure* tc);
   static void print_worker_threads_on(outputStream* st);
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -217,14 +217,6 @@
   product(uintx, G1HeapRegionSize, 0,                                       \
           "Size of the G1 regions.")                                        \
                                                                             \
-  experimental(bool, G1UseParallelRSetUpdating, true,                       \
-          "Enables the parallelization of remembered set updating "         \
-          "during evacuation pauses")                                       \
-                                                                            \
-  experimental(bool, G1UseParallelRSetScanning, true,                       \
-          "Enables the parallelization of remembered set scanning "         \
-          "during evacuation pauses")                                       \
-                                                                            \
   product(uintx, G1ConcRefinementThreads, 0,                                \
           "If non-0 is the number of parallel rem set update threads, "     \
           "otherwise the value is determined ergonomically.")               \
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,93 +47,55 @@
 size_t HeapRegion::CardsPerRegion    = 0;
 
 HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1,
-                                 HeapRegion* hr, ExtendedOopClosure* cl,
-                                 CardTableModRefBS::PrecisionStyle precision,
-                                 FilterKind fk) :
+                                 HeapRegion* hr,
+                                 G1ParPushHeapRSClosure* cl,
+                                 CardTableModRefBS::PrecisionStyle precision) :
   DirtyCardToOopClosure(hr, cl, precision, NULL),
-  _hr(hr), _fk(fk), _g1(g1) { }
+  _hr(hr), _rs_scan(cl), _g1(g1) { }
 
 FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r,
                                                    OopClosure* oc) :
   _r_bottom(r->bottom()), _r_end(r->end()), _oc(oc) { }
 
-template<class ClosureType>
-HeapWord* walk_mem_region_loop(ClosureType* cl, G1CollectedHeap* g1h,
-                               HeapRegion* hr,
-                               HeapWord* cur, HeapWord* top) {
-  oop cur_oop = oop(cur);
-  size_t oop_size = hr->block_size(cur);
-  HeapWord* next_obj = cur + oop_size;
-  while (next_obj < top) {
-    // Keep filtering the remembered set.
-    if (!g1h->is_obj_dead(cur_oop, hr)) {
-      // Bottom lies entirely below top, so we can call the
-      // non-memRegion version of oop_iterate below.
-      cur_oop->oop_iterate(cl);
-    }
-    cur = next_obj;
-    cur_oop = oop(cur);
-    oop_size = hr->block_size(cur);
-    next_obj = cur + oop_size;
-  }
-  return cur;
-}
-
 void HeapRegionDCTOC::walk_mem_region(MemRegion mr,
                                       HeapWord* bottom,
                                       HeapWord* top) {
   G1CollectedHeap* g1h = _g1;
   size_t oop_size;
-  ExtendedOopClosure* cl2 = NULL;
-
-  FilterIntoCSClosure intoCSFilt(this, g1h, _cl);
-  FilterOutOfRegionClosure outOfRegionFilt(_hr, _cl);
-
-  switch (_fk) {
-  case NoFilterKind:          cl2 = _cl; break;
-  case IntoCSFilterKind:      cl2 = &intoCSFilt; break;
-  case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break;
-  default:                    ShouldNotReachHere();
-  }
+  HeapWord* cur = bottom;
 
   // Start filtering what we add to the remembered set. If the object is
   // not considered dead, either because it is marked (in the mark bitmap)
   // or it was allocated after marking finished, then we add it. Otherwise
   // we can safely ignore the object.
-  if (!g1h->is_obj_dead(oop(bottom), _hr)) {
-    oop_size = oop(bottom)->oop_iterate(cl2, mr);
+  if (!g1h->is_obj_dead(oop(cur), _hr)) {
+    oop_size = oop(cur)->oop_iterate(_rs_scan, mr);
   } else {
-    oop_size = _hr->block_size(bottom);
+    oop_size = _hr->block_size(cur);
   }
 
-  bottom += oop_size;
-
-  if (bottom < top) {
-    // We replicate the loop below for several kinds of possible filters.
-    switch (_fk) {
-    case NoFilterKind:
-      bottom = walk_mem_region_loop(_cl, g1h, _hr, bottom, top);
-      break;
+  cur += oop_size;
 
-    case IntoCSFilterKind: {
-      FilterIntoCSClosure filt(this, g1h, _cl);
-      bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top);
-      break;
-    }
-
-    case OutOfRegionFilterKind: {
-      FilterOutOfRegionClosure filt(_hr, _cl);
-      bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top);
-      break;
-    }
-
-    default:
-      ShouldNotReachHere();
+  if (cur < top) {
+    oop cur_oop = oop(cur);
+    oop_size = _hr->block_size(cur);
+    HeapWord* next_obj = cur + oop_size;
+    while (next_obj < top) {
+      // Keep filtering the remembered set.
+      if (!g1h->is_obj_dead(cur_oop, _hr)) {
+        // Bottom lies entirely below top, so we can call the
+        // non-memRegion version of oop_iterate below.
+        cur_oop->oop_iterate(_rs_scan);
+      }
+      cur = next_obj;
+      cur_oop = oop(cur);
+      oop_size = _hr->block_size(cur);
+      next_obj = cur + oop_size;
     }
 
     // Last object. Need to do dead-obj filtering here too.
-    if (!g1h->is_obj_dead(oop(bottom), _hr)) {
-      oop(bottom)->oop_iterate(cl2, mr);
+    if (!g1h->is_obj_dead(oop(cur), _hr)) {
+      oop(cur)->oop_iterate(_rs_scan, mr);
     }
   }
 }
@@ -338,7 +300,7 @@
   _orig_end = mr.end();
   hr_clear(false /*par*/, false /*clear_space*/);
   set_top(bottom());
-  record_top_and_timestamp();
+  record_timestamp();
 }
 
 CompactibleSpace* HeapRegion::next_compaction_space() const {
@@ -426,9 +388,9 @@
 
   // If we're within a stop-world GC, then we might look at a card in a
   // GC alloc region that extends onto a GC LAB, which may not be
-  // parseable.  Stop such at the "saved_mark" of the region.
+  // parseable.  Stop such at the "scan_top" of the region.
   if (g1h->is_gc_active()) {
-    mr = mr.intersection(used_region_at_save_marks());
+    mr = mr.intersection(MemRegion(bottom(), scan_top()));
   } else {
     mr = mr.intersection(used_region());
   }
@@ -468,7 +430,7 @@
   oop obj;
 
   HeapWord* next = cur;
-  while (next <= start) {
+  do {
     cur = next;
     obj = oop(cur);
     if (obj->klass_or_null() == NULL) {
@@ -477,45 +439,38 @@
     }
     // Otherwise...
     next = cur + block_size(cur);
-  }
+  } while (next <= start);
 
   // If we finish the above loop...We have a parseable object that
   // begins on or before the start of the memory region, and ends
   // inside or spans the entire region.
-
-  assert(obj == oop(cur), "sanity");
   assert(cur <= start, "Loop postcondition");
   assert(obj->klass_or_null() != NULL, "Loop postcondition");
-  assert((cur + block_size(cur)) > start, "Loop postcondition");
 
-  if (!g1h->is_obj_dead(obj)) {
-    obj->oop_iterate(cl, mr);
-  }
-
-  while (cur < end) {
+  do {
     obj = oop(cur);
+    assert((cur + block_size(cur)) > (HeapWord*)obj, "Loop invariant");
     if (obj->klass_or_null() == NULL) {
       // Ran into an unparseable point.
       return cur;
-    };
+    }
 
-    // Otherwise:
-    next = cur + block_size(cur);
+    // Advance the current pointer. "obj" still points to the object to iterate.
+    cur = cur + block_size(cur);
 
     if (!g1h->is_obj_dead(obj)) {
-      if (next < end || !obj->is_objArray()) {
-        // This object either does not span the MemRegion
-        // boundary, or if it does it's not an array.
-        // Apply closure to whole object.
+      // Non-objArrays are sometimes marked imprecise at the object start. We
+      // always need to iterate over them in full.
+      // We only iterate over object arrays in full if they are completely contained
+      // in the memory region.
+      if (!obj->is_objArray() || (((HeapWord*)obj) >= start && cur <= end)) {
         obj->oop_iterate(cl);
       } else {
-        // This obj is an array that spans the boundary.
-        // Stop at the boundary.
         obj->oop_iterate(cl, mr);
       }
     }
-    cur = next;
-  }
+  } while (cur < end);
+
   return NULL;
 }
 
@@ -980,7 +935,7 @@
 
 void G1OffsetTableContigSpace::clear(bool mangle_space) {
   set_top(bottom());
-  set_saved_mark_word(bottom());
+  _scan_top = bottom();
   CompactibleSpace::clear(mangle_space);
   reset_bot();
 }
@@ -1012,41 +967,42 @@
   return _offsets.threshold();
 }
 
-HeapWord* G1OffsetTableContigSpace::saved_mark_word() const {
+HeapWord* G1OffsetTableContigSpace::scan_top() const {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  assert( _gc_time_stamp <= g1h->get_gc_time_stamp(), "invariant" );
   HeapWord* local_top = top();
   OrderAccess::loadload();
-  if (_gc_time_stamp < g1h->get_gc_time_stamp()) {
+  const unsigned local_time_stamp = _gc_time_stamp;
+  assert(local_time_stamp <= g1h->get_gc_time_stamp(), "invariant");
+  if (local_time_stamp < g1h->get_gc_time_stamp()) {
     return local_top;
   } else {
-    return Space::saved_mark_word();
+    return _scan_top;
   }
 }
 
-void G1OffsetTableContigSpace::record_top_and_timestamp() {
+void G1OffsetTableContigSpace::record_timestamp() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   unsigned curr_gc_time_stamp = g1h->get_gc_time_stamp();
 
   if (_gc_time_stamp < curr_gc_time_stamp) {
-    // The order of these is important, as another thread might be
-    // about to start scanning this region. If it does so after
-    // set_saved_mark and before _gc_time_stamp = ..., then the latter
-    // will be false, and it will pick up top() as the high water mark
-    // of region. If it does so after _gc_time_stamp = ..., then it
-    // will pick up the right saved_mark_word() as the high water mark
-    // of the region. Either way, the behaviour will be correct.
-    Space::set_saved_mark_word(top());
-    OrderAccess::storestore();
+    // Setting the time stamp here tells concurrent readers to look at
+    // scan_top to know the maximum allowed address to look at.
+
+    // scan_top should be bottom for all regions except for the
+    // retained old alloc region which should have scan_top == top
+    HeapWord* st = _scan_top;
+    guarantee(st == _bottom || st == _top, "invariant");
+
     _gc_time_stamp = curr_gc_time_stamp;
-    // No need to do another barrier to flush the writes above. If
-    // this is called in parallel with other threads trying to
-    // allocate into the region, the caller should call this while
-    // holding a lock and when the lock is released the writes will be
-    // flushed.
   }
 }
 
+void G1OffsetTableContigSpace::record_retained_region() {
+  // scan_top is the maximum address where it's safe for the next gc to
+  // scan this region.
+  _scan_top = top();
+}
+
 void G1OffsetTableContigSpace::safe_object_iterate(ObjectClosure* blk) {
   object_iterate(blk);
 }
@@ -1080,6 +1036,8 @@
 void G1OffsetTableContigSpace::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
   CompactibleSpace::initialize(mr, clear_space, mangle_space);
   _top = bottom();
+  _scan_top = bottom();
+  set_saved_mark_word(NULL);
   reset_bot();
 }
 
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -67,17 +67,9 @@
 // sets.
 
 class HeapRegionDCTOC : public DirtyCardToOopClosure {
-public:
-  // Specification of possible DirtyCardToOopClosure filtering.
-  enum FilterKind {
-    NoFilterKind,
-    IntoCSFilterKind,
-    OutOfRegionFilterKind
-  };
-
-protected:
+private:
   HeapRegion* _hr;
-  FilterKind _fk;
+  G1ParPushHeapRSClosure* _rs_scan;
   G1CollectedHeap* _g1;
 
   // Walk the given memory region from bottom to (actual) top
@@ -90,9 +82,9 @@
 
 public:
   HeapRegionDCTOC(G1CollectedHeap* g1,
-                  HeapRegion* hr, ExtendedOopClosure* cl,
-                  CardTableModRefBS::PrecisionStyle precision,
-                  FilterKind fk);
+                  HeapRegion* hr,
+                  G1ParPushHeapRSClosure* cl,
+                  CardTableModRefBS::PrecisionStyle precision);
 };
 
 // The complicating factor is that BlockOffsetTable diverged
@@ -101,28 +93,25 @@
 // OffsetTableContigSpace.  If the two versions of BlockOffsetTable could
 // be reconciled, then G1OffsetTableContigSpace could go away.
 
-// The idea behind time stamps is the following. Doing a save_marks on
-// all regions at every GC pause is time consuming (if I remember
-// well, 10ms or so). So, we would like to do that only for regions
-// that are GC alloc regions. To achieve this, we use time
-// stamps. For every evacuation pause, G1CollectedHeap generates a
-// unique time stamp (essentially a counter that gets
-// incremented). Every time we want to call save_marks on a region,
-// we set the saved_mark_word to top and also copy the current GC
-// time stamp to the time stamp field of the space. Reading the
-// saved_mark_word involves checking the time stamp of the
-// region. If it is the same as the current GC time stamp, then we
-// can safely read the saved_mark_word field, as it is valid. If the
-// time stamp of the region is not the same as the current GC time
-// stamp, then we instead read top, as the saved_mark_word field is
-// invalid. Time stamps (on the regions and also on the
-// G1CollectedHeap) are reset at every cleanup (we iterate over
-// the regions anyway) and at the end of a Full GC. The current scheme
-// that uses sequential unsigned ints will fail only if we have 4b
+// The idea behind time stamps is the following. We want to keep track of
+// the highest address where it's safe to scan objects for each region.
+// This is only relevant for current GC alloc regions so we keep a time stamp
+// per region to determine if the region has been allocated during the current
+// GC or not. If the time stamp is current we report a scan_top value which
+// was saved at the end of the previous GC for retained alloc regions and which is
+// equal to the bottom for all other regions.
+// There is a race between card scanners and allocating gc workers where we must ensure
+// that card scanners do not read the memory allocated by the gc workers.
+// In order to enforce that, we must not return a value of _top which is more recent than the
+// time stamp. This is due to the fact that a region may become a gc alloc region at
+// some point after we've read the timestamp value as being < the current time stamp.
+// The time stamps are re-initialized to zero at cleanup and at Full GCs.
+// The current scheme that uses sequential unsigned ints will fail only if we have 4b
 // evacuation pauses between two cleanups, which is _highly_ unlikely.
 class G1OffsetTableContigSpace: public CompactibleSpace {
   friend class VMStructs;
   HeapWord* _top;
+  HeapWord* volatile _scan_top;
  protected:
   G1BlockOffsetArrayContigSpace _offsets;
   Mutex _par_alloc_lock;
@@ -166,10 +155,11 @@
   void set_bottom(HeapWord* value);
   void set_end(HeapWord* value);
 
-  virtual HeapWord* saved_mark_word() const;
-  void record_top_and_timestamp();
+  HeapWord* scan_top() const;
+  void record_timestamp();
   void reset_gc_time_stamp() { _gc_time_stamp = 0; }
   unsigned get_gc_time_stamp() { return _gc_time_stamp; }
+  void record_retained_region();
 
   // See the comment above in the declaration of _pre_dummy_top for an
   // explanation of what it is.
@@ -193,6 +183,8 @@
   virtual HeapWord* allocate(size_t word_size);
   HeapWord* par_allocate(size_t word_size);
 
+  HeapWord* saved_mark_word() const { ShouldNotReachHere(); return NULL; }
+
   // MarkSweep support phase3
   virtual HeapWord* initialize_threshold();
   virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * 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,11 +31,15 @@
 #include "runtime/thread.inline.hpp"
 
 PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
-  _qset(qset), _buf(NULL), _index(0), _active(active),
+  _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active),
   _perm(perm), _lock(NULL)
 {}
 
-void PtrQueue::flush() {
+PtrQueue::~PtrQueue() {
+  assert(_perm || (_buf == NULL), "queue must be flushed before delete");
+}
+
+void PtrQueue::flush_impl() {
   if (!_perm && _buf != NULL) {
     if (_index == _sz) {
       // No work to do.
--- a/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,15 +65,18 @@
   Mutex* _lock;
 
   PtrQueueSet* qset() { return _qset; }
+  bool is_permanent() const { return _perm; }
+
+  // Process queue entries and release resources, if not permanent.
+  void flush_impl();
 
 public:
   // Initialize this queue to contain a null buffer, and be part of the
   // given PtrQueueSet.
   PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
-  // Release any contained resources.
-  virtual void flush();
-  // Calls flush() when destroyed.
-  ~PtrQueue() { flush(); }
+
+  // Requires queue flushed or permanent.
+  ~PtrQueue();
 
   // Associate a lock with a ptr queue.
   void set_lock(Mutex* lock) { _lock = lock; }
--- a/src/share/vm/gc_implementation/g1/satbQueue.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -39,7 +39,7 @@
   // first before we flush it, otherwise we might end up with an
   // enqueued buffer with refs into the CSet which breaks our invariants.
   filter();
-  PtrQueue::flush();
+  flush_impl();
 }
 
 // This method removes entries from an SATB buffer that will not be
--- a/src/share/vm/gc_implementation/g1/satbQueue.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,9 +60,8 @@
     // field to true. This is done in JavaThread::initialize_queues().
     PtrQueue(qset, perm, false /* active */) { }
 
-  // Overrides PtrQueue::flush() so that it can filter the buffer
-  // before it is flushed.
-  virtual void flush();
+  // Process queue entries and free resources.
+  void flush();
 
   // Overrides PtrQueue::should_enqueue_buffer(). See the method's
   // definition for more information.
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +34,11 @@
 #include "gc_implementation/g1/vm_operations_g1.hpp"
 #include "runtime/interfaceSupport.hpp"
 
-VM_G1CollectForAllocation::VM_G1CollectForAllocation(
-                                                  unsigned int gc_count_before,
-                                                  size_t word_size)
+VM_G1CollectForAllocation::VM_G1CollectForAllocation(uint gc_count_before,
+                                                     size_t word_size)
   : VM_G1OperationWithAllocRequest(gc_count_before, word_size,
                                    GCCause::_allocation_failure) {
-  guarantee(word_size > 0, "an allocation should always be requested");
+  guarantee(word_size != 0, "An allocation should always be requested with this operation.");
 }
 
 void VM_G1CollectForAllocation::doit() {
@@ -57,12 +56,11 @@
   g1h->do_full_collection(false /* clear_all_soft_refs */);
 }
 
-VM_G1IncCollectionPause::VM_G1IncCollectionPause(
-                                      unsigned int   gc_count_before,
-                                      size_t         word_size,
-                                      bool           should_initiate_conc_mark,
-                                      double         target_pause_time_ms,
-                                      GCCause::Cause gc_cause)
+VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint           gc_count_before,
+                                                 size_t         word_size,
+                                                 bool           should_initiate_conc_mark,
+                                                 double         target_pause_time_ms,
+                                                 GCCause::Cause gc_cause)
   : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
     _should_initiate_conc_mark(should_initiate_conc_mark),
     _target_pause_time_ms(target_pause_time_ms),
@@ -75,7 +73,7 @@
 }
 
 bool VM_G1IncCollectionPause::doit_prologue() {
-  bool res = VM_GC_Operation::doit_prologue();
+  bool res = VM_G1OperationWithAllocRequest::doit_prologue();
   if (!res) {
     if (_should_initiate_conc_mark) {
       // The prologue can fail for a couple of reasons. The first is that another GC
@@ -169,7 +167,7 @@
 }
 
 void VM_G1IncCollectionPause::doit_epilogue() {
-  VM_GC_Operation::doit_epilogue();
+  VM_G1OperationWithAllocRequest::doit_epilogue();
 
   // If the pause was initiated by a System.gc() and
   // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
@@ -230,7 +228,6 @@
 }
 
 void VM_CGC_Operation::doit() {
-  gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
   TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
   GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm(), G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id());
   SharedHeap* sh = SharedHeap::heap();
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,20 +36,17 @@
 //     - VM_G1CollectForAllocation
 //     - VM_G1IncCollectionPause
 
-class VM_G1OperationWithAllocRequest: public VM_GC_Operation {
+class VM_G1OperationWithAllocRequest : public VM_CollectForAllocation {
 protected:
-  size_t    _word_size;
-  HeapWord* _result;
   bool      _pause_succeeded;
   AllocationContext_t _allocation_context;
 
 public:
-  VM_G1OperationWithAllocRequest(unsigned int gc_count_before,
-                                 size_t       word_size,
+  VM_G1OperationWithAllocRequest(uint           gc_count_before,
+                                 size_t         word_size,
                                  GCCause::Cause gc_cause)
-    : VM_GC_Operation(gc_count_before, gc_cause),
-      _word_size(word_size), _result(NULL), _pause_succeeded(false) { }
-  HeapWord* result() { return _result; }
+    : VM_CollectForAllocation(word_size, gc_count_before, gc_cause),
+      _pause_succeeded(false) {}
   bool pause_succeeded() { return _pause_succeeded; }
   void set_allocation_context(AllocationContext_t context) { _allocation_context = context; }
   AllocationContext_t  allocation_context() { return _allocation_context; }
@@ -57,8 +54,8 @@
 
 class VM_G1CollectFull: public VM_GC_Operation {
 public:
-  VM_G1CollectFull(unsigned int gc_count_before,
-                   unsigned int full_gc_count_before,
+  VM_G1CollectFull(uint gc_count_before,
+                   uint full_gc_count_before,
                    GCCause::Cause cause)
     : VM_GC_Operation(gc_count_before, cause, full_gc_count_before, true) { }
   virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
@@ -70,7 +67,7 @@
 
 class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest {
 public:
-  VM_G1CollectForAllocation(unsigned int gc_count_before,
+  VM_G1CollectForAllocation(uint         gc_count_before,
                             size_t       word_size);
   virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
   virtual void doit();
@@ -84,9 +81,9 @@
   bool         _should_initiate_conc_mark;
   bool         _should_retry_gc;
   double       _target_pause_time_ms;
-  unsigned int _old_marking_cycles_completed_before;
+  uint         _old_marking_cycles_completed_before;
 public:
-  VM_G1IncCollectionPause(unsigned int   gc_count_before,
+  VM_G1IncCollectionPause(uint           gc_count_before,
                           size_t         word_size,
                           bool           should_initiate_conc_mark,
                           double         target_pause_time_ms,
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -622,7 +622,7 @@
                          true,  // Process younger gens, if any,
                                 // as strong roots.
                          false, // no scope; this is parallel code
-                         SharedHeap::SO_ScavengeCodeCache,
+                         GenCollectedHeap::SO_ScavengeCodeCache,
                          GenCollectedHeap::StrongAndWeakRoots,
                          &par_scan_state.to_space_root_closure(),
                          &par_scan_state.older_gen_closure(),
@@ -1197,8 +1197,10 @@
         return real_forwardee(old);
     }
 
-    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
-                                       old, m, sz);
+    if (!_promotion_failed) {
+      new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
+                                        old, m, sz);
+    }
 
     if (new_obj == NULL) {
       // promotion failed, forward to self
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -261,7 +261,7 @@
 
   uint loop_count = 0;
   uint gc_count = 0;
-  int gclocker_stalled_count = 0;
+  uint gclocker_stalled_count = 0;
 
   while (result == NULL) {
     // We don't want to have multiple collections for a single filled generation.
@@ -521,8 +521,8 @@
   assert(!Heap_lock->owned_by_self(),
     "this thread should not own the Heap_lock");
 
-  unsigned int gc_count      = 0;
-  unsigned int full_gc_count = 0;
+  uint gc_count      = 0;
+  uint full_gc_count = 0;
   {
     MutexLocker ml(Heap_lock);
     // This value is guarded by the Heap_lock
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -167,7 +167,6 @@
   {
     HandleMark hm;
 
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer->gc_id());
     TraceCollectorStats tcs(counters());
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -2054,7 +2054,6 @@
     gc_task_manager()->task_idle_workers();
     heap->set_par_threads(gc_task_manager()->active_workers());
 
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id());
     TraceCollectorStats tcs(counters());
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -329,7 +329,6 @@
     ResourceMark rm;
     HandleMark hm;
 
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id());
     TraceCollectorStats tcs(counters());
--- a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +32,10 @@
 #include "utilities/dtrace.hpp"
 
 // The following methods are used by the parallel scavenge collector
-VM_ParallelGCFailedAllocation::VM_ParallelGCFailedAllocation(size_t size,
-                                                      unsigned int gc_count) :
-  VM_GC_Operation(gc_count, GCCause::_allocation_failure),
-  _size(size),
-  _result(NULL)
-{
+VM_ParallelGCFailedAllocation::VM_ParallelGCFailedAllocation(size_t word_size,
+                                                             uint gc_count) :
+    VM_CollectForAllocation(word_size, gc_count, GCCause::_allocation_failure) {
+  assert(word_size != 0, "An allocation should always be requested with this operation.");
 }
 
 void VM_ParallelGCFailedAllocation::doit() {
@@ -47,7 +45,7 @@
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
 
   GCCauseSetter gccs(heap, _gc_cause);
-  _result = heap->failed_mem_allocate(_size);
+  _result = heap->failed_mem_allocate(_word_size);
 
   if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
@@ -55,8 +53,8 @@
 }
 
 // Only used for System.gc() calls
-VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(unsigned int gc_count,
-                                             unsigned int full_gc_count,
+VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(uint gc_count,
+                                             uint full_gc_count,
                                              GCCause::Cause gc_cause) :
   VM_GC_Operation(gc_count, gc_cause, full_gc_count, true /* full */)
 {
--- a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,26 +29,19 @@
 #include "gc_implementation/shared/vmGCOperations.hpp"
 #include "gc_interface/gcCause.hpp"
 
-class VM_ParallelGCFailedAllocation: public VM_GC_Operation {
- private:
-  size_t    _size;
-  HeapWord* _result;
-
+class VM_ParallelGCFailedAllocation : public VM_CollectForAllocation {
  public:
-  VM_ParallelGCFailedAllocation(size_t size, unsigned int gc_count);
+  VM_ParallelGCFailedAllocation(size_t word_size, uint gc_count);
 
   virtual VMOp_Type type() const {
     return VMOp_ParallelGCFailedAllocation;
   }
   virtual void doit();
-
-  HeapWord* result() const       { return _result; }
 };
 
 class VM_ParallelGCSystemGC: public VM_GC_Operation {
  public:
-  VM_ParallelGCSystemGC(unsigned int gc_count, unsigned int full_gc_count,
-                        GCCause::Cause gc_cause);
+  VM_ParallelGCSystemGC(uint gc_count, uint full_gc_count, GCCause::Cause gc_cause);
   virtual VMOp_Type type() const { return VMOp_ParallelGCSystemGC; }
   virtual void doit();
 };
--- a/src/share/vm/gc_implementation/shared/ageTable.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/shared/ageTable.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -55,7 +55,10 @@
 
   // add entry
   void add(oop p, size_t oop_size) {
-    uint age = p->age();
+    add(p->age(), oop_size);
+  }
+
+  void add(uint age, size_t oop_size) {
     assert(age > 0 && age < table_size, "invalid age of object");
     sizes[age] += oop_size;
   }
--- a/src/share/vm/gc_implementation/shared/gcTraceTime.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/shared/gcTraceTime.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -49,10 +49,8 @@
   }
 
   if (_doit) {
-    if (PrintGCTimeStamps) {
-      gclog_or_tty->stamp();
-      gclog_or_tty->print(": ");
-    }
+    gclog_or_tty->date_stamp(PrintGCDateStamps);
+    gclog_or_tty->stamp(PrintGCTimeStamps);
     if (PrintGCID) {
       gclog_or_tty->print("#%u: ", gc_id.id());
     }
--- a/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -63,7 +63,8 @@
   virtual ~ParGCAllocBuffer() {}
 
   static const size_t min_size() {
-    return ThreadLocalAllocBuffer::min_size();
+    // Make sure that we return something that is larger than AlignmentReserve
+    return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
   }
 
   static const size_t max_size() {
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -193,10 +193,10 @@
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   GCCauseSetter gccs(gch, _gc_cause);
-  _res = gch->satisfy_failed_allocation(_size, _tlab);
-  assert(gch->is_in_reserved_or_null(_res), "result not in heap");
+  _result = gch->satisfy_failed_allocation(_word_size, _tlab);
+  assert(gch->is_in_reserved_or_null(_result), "result not in heap");
 
-  if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
+  if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
 }
@@ -209,6 +209,18 @@
   gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
 }
 
+VM_CollectForMetadataAllocation::VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
+                                                                 size_t size,
+                                                                 Metaspace::MetadataType mdtype,
+                                                                 uint gc_count_before,
+                                                                 uint full_gc_count_before,
+                                                                 GCCause::Cause gc_cause)
+    : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
+      _loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
+  assert(_size != 0, "An allocation should always be requested with this operation.");
+  AllocTracer::send_allocation_requiring_gc_event(_size * HeapWordSize, GCId::peek());
+}
+
 // Returns true iff concurrent GCs unloads metadata.
 bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
 #if INCLUDE_ALL_GCS
@@ -313,3 +325,11 @@
     set_gc_locked();
   }
 }
+
+VM_CollectForAllocation::VM_CollectForAllocation(size_t word_size, uint gc_count_before, GCCause::Cause cause)
+    : VM_GC_Operation(gc_count_before, cause), _result(NULL), _word_size(word_size) {
+  // Only report if operation was really caused by an allocation.
+  if (_word_size != 0) {
+    AllocTracer::send_allocation_requiring_gc_event(_word_size * HeapWordSize, GCId::peek());
+  }
+}
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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_GC_IMPLEMENTATION_SHARED_VMGCOPERATIONS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_VMGCOPERATIONS_HPP
 
+#include "gc_implementation/shared/gcId.hpp"
 #include "memory/heapInspection.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/jniHandles.hpp"
@@ -38,11 +39,12 @@
 //  VM_Operation
 //      VM_GC_Operation
 //          VM_GC_HeapInspection
-//          VM_GenCollectForAllocation
 //          VM_GenCollectFull
 //          VM_GenCollectFullConcurrent
-//          VM_ParallelGCFailedAllocation
 //          VM_ParallelGCSystemGC
+//          VM_CollectForAllocation
+//              VM_GenCollectForAllocation
+//              VM_ParallelGCFailedAllocation
 //  VM_GC_Operation
 //   - implements methods common to all classes in the hierarchy:
 //     prevents multiple gc requests and manages lock on heap;
@@ -51,6 +53,7 @@
 //   - prints class histogram on SIGBREAK if PrintClassHistogram
 //     is specified; and also the attach "inspectheap" operation
 //
+//  VM_CollectForAllocation
 //  VM_GenCollectForAllocation
 //  VM_ParallelGCFailedAllocation
 //   - this operation is invoked when allocation is failed;
@@ -66,13 +69,13 @@
 
 class VM_GC_Operation: public VM_Operation {
  protected:
-  BasicLock     _pending_list_basic_lock; // for refs pending list notification (PLL)
-  unsigned int  _gc_count_before;         // gc count before acquiring PLL
-  unsigned int  _full_gc_count_before;    // full gc count before acquiring PLL
-  bool          _full;                    // whether a "full" collection
-  bool          _prologue_succeeded;      // whether doit_prologue succeeded
+  BasicLock      _pending_list_basic_lock; // for refs pending list notification (PLL)
+  uint           _gc_count_before;         // gc count before acquiring PLL
+  uint           _full_gc_count_before;    // full gc count before acquiring PLL
+  bool           _full;                    // whether a "full" collection
+  bool           _prologue_succeeded;      // whether doit_prologue succeeded
   GCCause::Cause _gc_cause;                // the putative cause for this gc op
-  bool          _gc_locked;               // will be set if gc was locked
+  bool           _gc_locked;               // will be set if gc was locked
 
   virtual bool skip_operation() const;
 
@@ -81,9 +84,9 @@
   void release_and_notify_pending_list_lock();
 
  public:
-  VM_GC_Operation(unsigned int gc_count_before,
+  VM_GC_Operation(uint gc_count_before,
                   GCCause::Cause _cause,
-                  unsigned int full_gc_count_before = 0,
+                  uint full_gc_count_before = 0,
                   bool full = false) {
     _full = full;
     _prologue_succeeded = false;
@@ -160,38 +163,45 @@
   bool collect();
 };
 
+class VM_CollectForAllocation : public VM_GC_Operation {
+ protected:
+  size_t    _word_size; // Size of object to be allocated (in number of words)
+  HeapWord* _result;    // Allocation result (NULL if allocation failed)
 
-class VM_GenCollectForAllocation: public VM_GC_Operation {
+ public:
+  VM_CollectForAllocation(size_t word_size, uint gc_count_before, GCCause::Cause cause);
+
+  HeapWord* result() const {
+    return _result;
+  }
+};
+
+class VM_GenCollectForAllocation : public VM_CollectForAllocation {
  private:
-  HeapWord*   _res;
-  size_t      _size;                       // size of object to be allocated.
   bool        _tlab;                       // alloc is of a tlab.
  public:
-  VM_GenCollectForAllocation(size_t size,
+  VM_GenCollectForAllocation(size_t word_size,
                              bool tlab,
-                             unsigned int gc_count_before)
-    : VM_GC_Operation(gc_count_before, GCCause::_allocation_failure),
-      _size(size),
+                             uint gc_count_before)
+    : VM_CollectForAllocation(word_size, gc_count_before, GCCause::_allocation_failure),
       _tlab(tlab) {
-    _res = NULL;
+    assert(word_size != 0, "An allocation should always be requested with this operation.");
   }
   ~VM_GenCollectForAllocation()  {}
   virtual VMOp_Type type() const { return VMOp_GenCollectForAllocation; }
   virtual void doit();
-  HeapWord* result() const       { return _res; }
 };
 
-
 // VM operation to invoke a collection of the heap as a
 // GenCollectedHeap heap.
 class VM_GenCollectFull: public VM_GC_Operation {
  private:
   int _max_level;
  public:
-  VM_GenCollectFull(unsigned int gc_count_before,
-                    unsigned int full_gc_count_before,
+  VM_GenCollectFull(uint gc_count_before,
+                    uint full_gc_count_before,
                     GCCause::Cause gc_cause,
-                      int max_level)
+                    int max_level)
     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
       _max_level(max_level) { }
   ~VM_GenCollectFull() {}
@@ -208,12 +218,9 @@
  public:
   VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
                                   size_t size, Metaspace::MetadataType mdtype,
-                                      unsigned int gc_count_before,
-                                      unsigned int full_gc_count_before,
-                                      GCCause::Cause gc_cause)
-    : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
-      _loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
-  }
+                                  uint gc_count_before,
+                                  uint full_gc_count_before,
+                                  GCCause::Cause gc_cause);
   virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
   virtual void doit();
   MetaWord* result() const       { return _result; }
--- a/src/share/vm/gc_interface/allocTracer.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_interface/allocTracer.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "gc_interface/allocTracer.hpp"
 #include "trace/tracing.hpp"
 #include "runtime/handles.hpp"
@@ -46,3 +47,12 @@
     event.commit();
   }
 }
+
+void AllocTracer::send_allocation_requiring_gc_event(size_t size, const GCId& gcId) {
+  EventAllocationRequiringGC event;
+  if (event.should_commit()) {
+    event.set_gcId(gcId.id());
+    event.set_size(size);
+    event.commit();
+  }
+}
--- a/src/share/vm/gc_interface/allocTracer.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/gc_interface/allocTracer.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 @@
   public:
     static void send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size);
     static void send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size);
+    static void send_allocation_requiring_gc_event(size_t size, const GCId& gcId);
 };
 
 #endif /* SHARE_VM_GC_INTERFACE_ALLOCTRACER_HPP */
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,22 +30,15 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/top.hpp"
-#ifdef TARGET_ARCH_x86
+#if defined INTERP_MASM_MD_HPP
+# include INTERP_MASM_MD_HPP
+#elif defined TARGET_ARCH_x86
 # include "interp_masm_x86.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "interp_masm_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "interp_masm_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "interp_masm_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "interp_masm_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "interp_masm_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -3432,7 +3432,7 @@
   tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf);
   tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry);
   tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link);
-  tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp);
+  tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) p2i(this->_oop_temp));
   tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
   tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit);
   tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base);
--- a/src/share/vm/interpreter/bytecodes.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/bytecodes.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -420,6 +420,7 @@
   static bool        is_astore      (Code code)    { return (code == _astore || code == _astore_0 || code == _astore_1
                                                                              || code == _astore_2 || code == _astore_3); }
 
+  static bool        is_store_into_local(Code code){ return (_istore <= code && code <= _astore_3); }
   static bool        is_const       (Code code)    { return (_aconst_null <= code && code <= _ldc2_w); }
   static bool        is_zero_const  (Code code)    { return (code == _aconst_null || code == _iconst_0
                                                            || code == _fconst_0 || code == _dconst_0); }
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -407,7 +407,11 @@
     // during deoptimization so the interpreter needs to skip it when
     // the frame is popped.
     thread->set_do_not_unlock_if_synchronized(true);
+#ifdef CC_INTERP
+    return (address) -1;
+#else
     return Interpreter::remove_activation_entry();
+#endif
   }
 
   // Need to do this check first since when _do_not_unlock_if_synchronized
--- a/src/share/vm/interpreter/linkResolver.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/linkResolver.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -320,7 +320,7 @@
   // First check in default method array
   if (!resolved_method->is_abstract() &&
     (InstanceKlass::cast(klass())->default_methods() != NULL)) {
-    int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false);
+    int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false, false);
     if (index >= 0 ) {
       vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
     }
--- a/src/share/vm/interpreter/oopMapCache.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/oopMapCache.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -244,10 +244,8 @@
   method()->print_value();
   tty->print(" @ %d = [%d] { ", bci(), n);
   for (int i = 0; i < n; i++) {
-#ifdef ENABLE_ZAP_DEAD_LOCALS
     if (is_dead(i)) tty->print("%d+ ", i);
     else
-#endif
     if (is_oop(i)) tty->print("%d ", i);
   }
   tty->print_cr("}");
@@ -402,13 +400,11 @@
       value |= (mask << oop_bit_number );
     }
 
-  #ifdef ENABLE_ZAP_DEAD_LOCALS
     // set dead bit
     if (!cell->is_live()) {
       value |= (mask << dead_bit_number);
       assert(!cell->is_reference(), "dead value marked as oop");
     }
-  #endif
   }
 
   // make sure last word is stored
--- a/src/share/vm/interpreter/oopMapCache.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/oopMapCache.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -66,19 +66,15 @@
 
  public:
   enum {
-    N                = 2,                // the number of words reserved
+    N                = 4,                // the number of words reserved
                                          // for inlined mask storage
     small_mask_limit = N * BitsPerWord,  // the maximum number of bits
                                          // available for small masks,
                                          // small_mask_limit can be set to 0
                                          // for testing bit_mask allocation
 
-#ifdef ENABLE_ZAP_DEAD_LOCALS
     bits_per_entry   = 2,
     dead_bit_number  = 1,
-#else
-    bits_per_entry   = 1,
-#endif
     oop_bit_number   = 0
   };
 
@@ -119,10 +115,6 @@
 
   void set_expression_stack_size(int sz)         { _expression_stack_size = sz; }
 
-#ifdef ENABLE_ZAP_DEAD_LOCALS
-  bool is_dead(int offset) const                 { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
-#endif
-
   // Lookup
   bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; }
   bool is_empty() const;
@@ -144,6 +136,7 @@
   void print() const;
 
   int number_of_entries() const                  { return mask_size() / bits_per_entry; }
+  bool is_dead(int offset) const                 { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
   bool is_oop (int offset) const                 { return (entry_at(offset) & (1 << oop_bit_number )) != 0; }
 
   int expression_stack_size() const              { return _expression_stack_size; }
--- a/src/share/vm/interpreter/templateTable.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/interpreter/templateTable.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,22 +28,15 @@
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/frame.hpp"
-#ifdef TARGET_ARCH_x86
+#if defined INTERP_MASM_MD_HPP
+# include INTERP_MASM_MD_HPP
+#elif defined TARGET_ARCH_x86
 # include "interp_masm_x86.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "interp_masm_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "interp_masm_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "interp_masm_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "interp_masm_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "interp_masm_ppc_64.hpp"
 #endif
 
@@ -358,25 +351,17 @@
   static Template* template_for_wide(Bytecodes::Code code)  { Bytecodes::wide_check(code); return &_template_table_wide[code]; }
 
   // Platform specifics
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined TEMPLATETABLE_MD_HPP
+# include TEMPLATETABLE_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "templateTable_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "templateTable_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "templateTable_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "templateTable_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "templateTable_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "templateTable_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "templateTable_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/memory/collectorPolicy.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/collectorPolicy.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -656,7 +656,7 @@
 
   // Loop until the allocation is satisified,
   // or unsatisfied after GC.
-  for (int try_count = 1, gclocker_stalled_count = 0; /* return or throw */; try_count += 1) {
+  for (uint 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.
@@ -670,7 +670,7 @@
         return result;
       }
     }
-    unsigned int gc_count_before;  // read inside the Heap_lock locked region
+    uint gc_count_before;  // read inside the Heap_lock locked region
     {
       MutexLocker ml(Heap_lock);
       if (PrintGC && Verbose) {
--- a/src/share/vm/memory/defNewGeneration.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/defNewGeneration.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -629,7 +629,7 @@
                          true,  // Process younger gens, if any,
                                 // as strong roots.
                          true,  // activate StrongRootsScope
-                         SharedHeap::SO_ScavengeCodeCache,
+                         GenCollectedHeap::SO_ScavengeCodeCache,
                          GenCollectedHeap::StrongAndWeakRoots,
                          &fsc_with_no_gc_barrier,
                          &fsc_with_gc_barrier,
--- a/src/share/vm/memory/genCollectedHeap.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -26,6 +26,7 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/codeCache.hpp"
 #include "code/icBuffer.hpp"
 #include "gc_implementation/shared/collectorCounters.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
@@ -49,6 +50,7 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/vmThread.hpp"
+#include "services/management.hpp"
 #include "services/memoryService.hpp"
 #include "utilities/vmError.hpp"
 #include "utilities/workgroup.hpp"
@@ -63,7 +65,15 @@
 
 // The set of potentially parallel tasks in root scanning.
 enum GCH_strong_roots_tasks {
-  // We probably want to parallelize both of these internally, but for now...
+  GCH_PS_Universe_oops_do,
+  GCH_PS_JNIHandles_oops_do,
+  GCH_PS_ObjectSynchronizer_oops_do,
+  GCH_PS_FlatProfiler_oops_do,
+  GCH_PS_Management_oops_do,
+  GCH_PS_SystemDictionary_oops_do,
+  GCH_PS_ClassLoaderDataGraph_oops_do,
+  GCH_PS_jvmti_oops_do,
+  GCH_PS_CodeCache_oops_do,
   GCH_PS_younger_gens,
   // Leave this one last.
   GCH_PS_NumElements
@@ -72,13 +82,9 @@
 GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :
   SharedHeap(policy),
   _gen_policy(policy),
-  _gen_process_roots_tasks(new SubTasksDone(GCH_PS_NumElements)),
+  _process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),
   _full_collections_completed(0)
 {
-  if (_gen_process_roots_tasks == NULL ||
-      !_gen_process_roots_tasks->valid()) {
-    vm_exit_during_initialization("Failed necessary allocation.");
-  }
   assert(policy != NULL, "Sanity check");
 }
 
@@ -384,7 +390,6 @@
 
     bool complete = full && (max_level == (n_gens()-1));
     const char* gc_cause_prefix = complete ? "Full GC" : "GC";
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later
     // so we can assume here that the next GC id is what we want.
@@ -590,29 +595,137 @@
 
 void GenCollectedHeap::set_par_threads(uint t) {
   SharedHeap::set_par_threads(t);
-  _gen_process_roots_tasks->set_n_threads(t);
+  set_n_termination(t);
+}
+
+void GenCollectedHeap::set_n_termination(uint t) {
+  _process_strong_tasks->set_n_threads(t);
 }
 
-void GenCollectedHeap::
-gen_process_roots(int level,
-                  bool younger_gens_as_roots,
-                  bool activate_scope,
-                  SharedHeap::ScanningOption so,
-                  OopsInGenClosure* not_older_gens,
-                  OopsInGenClosure* weak_roots,
-                  OopsInGenClosure* older_gens,
-                  CLDClosure* cld_closure,
-                  CLDClosure* weak_cld_closure,
-                  CodeBlobClosure* code_closure) {
+#ifdef ASSERT
+class AssertNonScavengableClosure: public OopClosure {
+public:
+  virtual void do_oop(oop* p) {
+    assert(!Universe::heap()->is_in_partial_collection(*p),
+      "Referent should not be scavengable.");  }
+  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+};
+static AssertNonScavengableClosure assert_is_non_scavengable_closure;
+#endif
+
+void GenCollectedHeap::process_roots(bool activate_scope,
+                                     ScanningOption so,
+                                     OopClosure* strong_roots,
+                                     OopClosure* weak_roots,
+                                     CLDClosure* strong_cld_closure,
+                                     CLDClosure* weak_cld_closure,
+                                     CodeBlobClosure* code_roots) {
+  StrongRootsScope srs(this, activate_scope);
 
   // General roots.
-  SharedHeap::process_roots(activate_scope, so,
-                            not_older_gens, weak_roots,
-                            cld_closure, weak_cld_closure,
-                            code_closure);
+  assert(_strong_roots_parity != 0, "must have called prologue code");
+  assert(code_roots != NULL, "code root closure should always be set");
+  // _n_termination for _process_strong_tasks should be set up stream
+  // in a method not running in a GC worker.  Otherwise the GC worker
+  // could be trying to change the termination condition while the task
+  // is executing in another GC worker.
+
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_ClassLoaderDataGraph_oops_do)) {
+    ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);
+  }
+
+  // Some CLDs contained in the thread frames should be considered strong.
+  // Don't process them if they will be processed during the ClassLoaderDataGraph phase.
+  CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
+  // Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway
+  CodeBlobClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
+
+  Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);
+
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_Universe_oops_do)) {
+    Universe::oops_do(strong_roots);
+  }
+  // Global (strong) JNI handles
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_JNIHandles_oops_do)) {
+    JNIHandles::oops_do(strong_roots);
+  }
+
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_ObjectSynchronizer_oops_do)) {
+    ObjectSynchronizer::oops_do(strong_roots);
+  }
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_FlatProfiler_oops_do)) {
+    FlatProfiler::oops_do(strong_roots);
+  }
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_Management_oops_do)) {
+    Management::oops_do(strong_roots);
+  }
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_jvmti_oops_do)) {
+    JvmtiExport::oops_do(strong_roots);
+  }
+
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_SystemDictionary_oops_do)) {
+    SystemDictionary::roots_oops_do(strong_roots, weak_roots);
+  }
+
+  // All threads execute the following. A specific chunk of buckets
+  // from the StringTable are the individual tasks.
+  if (weak_roots != NULL) {
+    if (CollectedHeap::use_parallel_gc_threads()) {
+      StringTable::possibly_parallel_oops_do(weak_roots);
+    } else {
+      StringTable::oops_do(weak_roots);
+    }
+  }
+
+  if (!_process_strong_tasks->is_task_claimed(GCH_PS_CodeCache_oops_do)) {
+    if (so & SO_ScavengeCodeCache) {
+      assert(code_roots != NULL, "must supply closure for code cache");
+
+      // We only visit parts of the CodeCache when scavenging.
+      CodeCache::scavenge_root_nmethods_do(code_roots);
+    }
+    if (so & SO_AllCodeCache) {
+      assert(code_roots != NULL, "must supply closure for code cache");
+
+      // CMSCollector uses this to do intermediate-strength collections.
+      // We scan the entire code cache, since CodeCache::do_unloading is not called.
+      CodeCache::blobs_do(code_roots);
+    }
+    // Verify that the code cache contents are not subject to
+    // movement by a scavenging collection.
+    DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations));
+    DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
+  }
+
+}
+
+void GenCollectedHeap::gen_process_roots(int level,
+                                         bool younger_gens_as_roots,
+                                         bool activate_scope,
+                                         ScanningOption so,
+                                         bool only_strong_roots,
+                                         OopsInGenClosure* not_older_gens,
+                                         OopsInGenClosure* older_gens,
+                                         CLDClosure* cld_closure) {
+  const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
+
+  bool is_moving_collection = false;
+  if (level == 0 || is_adjust_phase) {
+    // young collections are always moving
+    is_moving_collection = true;
+  }
+
+  MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection);
+  OopsInGenClosure* weak_roots = only_strong_roots ? NULL : not_older_gens;
+  CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
+
+  process_roots(activate_scope, so,
+                not_older_gens, weak_roots,
+                cld_closure, weak_cld_closure,
+                &mark_code_closure);
 
   if (younger_gens_as_roots) {
-    if (!_gen_process_roots_tasks->is_task_claimed(GCH_PS_younger_gens)) {
+    if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
       for (int i = 0; i < level; i++) {
         not_older_gens->set_generation(_gens[i]);
         _gens[i]->oop_iterate(not_older_gens);
@@ -628,43 +741,18 @@
     older_gens->reset_generation();
   }
 
-  _gen_process_roots_tasks->all_tasks_completed();
+  _process_strong_tasks->all_tasks_completed();
 }
 
-void GenCollectedHeap::
-gen_process_roots(int level,
-                  bool younger_gens_as_roots,
-                  bool activate_scope,
-                  SharedHeap::ScanningOption so,
-                  bool only_strong_roots,
-                  OopsInGenClosure* not_older_gens,
-                  OopsInGenClosure* older_gens,
-                  CLDClosure* cld_closure) {
 
-  const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
-
-  bool is_moving_collection = false;
-  if (level == 0 || is_adjust_phase) {
-    // young collections are always moving
-    is_moving_collection = true;
-  }
-
-  MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection);
-  CodeBlobClosure* code_closure = &mark_code_closure;
-
-  gen_process_roots(level,
-                    younger_gens_as_roots,
-                    activate_scope, so,
-                    not_older_gens, only_strong_roots ? NULL : not_older_gens,
-                    older_gens,
-                    cld_closure, only_strong_roots ? NULL : cld_closure,
-                    code_closure);
-
-}
+class AlwaysTrueClosure: public BoolObjectClosure {
+public:
+  bool do_object_b(oop p) { return true; }
+};
+static AlwaysTrueClosure always_true;
 
 void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {
-  SharedHeap::process_weak_roots(root_closure);
-  // "Local" "weak" refs
+  JNIHandles::weak_oops_do(&always_true, root_closure);
   for (int i = 0; i < _n_gens; i++) {
     _gens[i]->ref_processor()->weak_oops_do(root_closure);
   }
--- a/src/share/vm/memory/genCollectedHeap.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/genCollectedHeap.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -79,8 +79,7 @@
 
   // Data structure for claiming the (potentially) parallel tasks in
   // (gen-specific) roots processing.
-  SubTasksDone* _gen_process_roots_tasks;
-  SubTasksDone* gen_process_roots_tasks() { return _gen_process_roots_tasks; }
+  SubTasksDone* _process_strong_tasks;
 
   // In block contents verification, the number of header words to skip
   NOT_PRODUCT(static size_t _skip_header_HeapWords;)
@@ -390,6 +389,7 @@
   static GenCollectedHeap* heap();
 
   void set_par_threads(uint t);
+  void set_n_termination(uint t);
 
   // Invoke the "do_oop" method of one of the closures "not_older_gens"
   // or "older_gens" on root locations for the generation at
@@ -403,11 +403,25 @@
   // The "so" argument determines which of the roots
   // the closure is applied to:
   // "SO_None" does none;
+  enum ScanningOption {
+    SO_None                =  0x0,
+    SO_AllCodeCache        =  0x8,
+    SO_ScavengeCodeCache   = 0x10
+  };
+
  private:
+  void process_roots(bool activate_scope,
+                     ScanningOption so,
+                     OopClosure* strong_roots,
+                     OopClosure* weak_roots,
+                     CLDClosure* strong_cld_closure,
+                     CLDClosure* weak_cld_closure,
+                     CodeBlobClosure* code_roots);
+
   void gen_process_roots(int level,
                          bool younger_gens_as_roots,
                          bool activate_scope,
-                         SharedHeap::ScanningOption so,
+                         ScanningOption so,
                          OopsInGenClosure* not_older_gens,
                          OopsInGenClosure* weak_roots,
                          OopsInGenClosure* older_gens,
@@ -422,7 +436,7 @@
   void gen_process_roots(int level,
                          bool younger_gens_as_roots,
                          bool activate_scope,
-                         SharedHeap::ScanningOption so,
+                         ScanningOption so,
                          bool only_strong_roots,
                          OopsInGenClosure* not_older_gens,
                          OopsInGenClosure* older_gens,
--- a/src/share/vm/memory/genMarkSweep.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/genMarkSweep.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -210,7 +210,7 @@
   gch->gen_process_roots(level,
                          false, // Younger gens are not roots.
                          true,  // activate StrongRootsScope
-                         SharedHeap::SO_None,
+                         GenCollectedHeap::SO_None,
                          GenCollectedHeap::StrongRootsOnly,
                          &follow_root_closure,
                          &follow_root_closure,
@@ -295,7 +295,7 @@
   gch->gen_process_roots(level,
                          false, // Younger gens are not roots.
                          true,  // activate StrongRootsScope
-                         SharedHeap::SO_AllCodeCache,
+                         GenCollectedHeap::SO_AllCodeCache,
                          GenCollectedHeap::StrongAndWeakRoots,
                          &adjust_pointer_closure,
                          &adjust_pointer_closure,
--- a/src/share/vm/memory/generation.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/generation.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -145,7 +145,7 @@
     // GenGrain.
     // Note: on ARM we add 1 bit for card_table_base to be properly aligned
     // (we expect its low byte to be zero - see implementation of post_barrier)
-    LogOfGenGrain = 16 ARM_ONLY(+1),
+    LogOfGenGrain = 16 ARM32_ONLY(+1),
     GenGrain = 1 << LogOfGenGrain
   };
 
--- a/src/share/vm/memory/guardedMemory.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/guardedMemory.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -235,7 +235,7 @@
    * @return the size of the user data.
    */
   size_t get_user_size() const {
-    assert(_base_addr, "Not wrapping any memory");
+    assert(_base_addr != NULL, "Not wrapping any memory");
     return get_head_guard()->get_user_size();
   }
 
@@ -245,7 +245,7 @@
    * @return the user data pointer.
    */
   u_char* get_user_ptr() const {
-    assert(_base_addr, "Not wrapping any memory");
+    assert(_base_addr != NULL, "Not wrapping any memory");
     return _base_addr + sizeof(GuardHeader);
   }
 
@@ -281,7 +281,7 @@
     memset(get_user_ptr(), ch, get_user_size());
   }
 
-public:
+ public:
   /**
    * Return the total size required for wrapping the given user size.
    *
--- a/src/share/vm/memory/referenceProcessor.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/referenceProcessor.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -118,6 +118,7 @@
   _discoveredWeakRefs    = &_discoveredSoftRefs[_max_num_q];
   _discoveredFinalRefs   = &_discoveredWeakRefs[_max_num_q];
   _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
+  _discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q];
 
   // Initialize all entries to NULL
   for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
@@ -246,6 +247,13 @@
     phantom_count =
       process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
                                  is_alive, keep_alive, complete_gc, task_executor);
+
+    // Process cleaners, but include them in phantom statistics.  We expect
+    // Cleaner references to be temporary, and don't want to deal with
+    // possible incompatibilities arising from making it more visible.
+    phantom_count +=
+      process_discovered_reflist(_discoveredCleanerRefs, NULL, true,
+                                 is_alive, keep_alive, complete_gc, task_executor);
   }
 
   // Weak global JNI references. It would make more sense (semantically) to
@@ -883,6 +891,7 @@
   balance_queues(_discoveredWeakRefs);
   balance_queues(_discoveredFinalRefs);
   balance_queues(_discoveredPhantomRefs);
+  balance_queues(_discoveredCleanerRefs);
 }
 
 size_t
@@ -1042,6 +1051,9 @@
     case REF_PHANTOM:
       list = &_discoveredPhantomRefs[id];
       break;
+    case REF_CLEANER:
+      list = &_discoveredCleanerRefs[id];
+      break;
     case REF_NONE:
       // we should not reach here if we are an InstanceRefKlass
     default:
@@ -1307,6 +1319,17 @@
       preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
                                   keep_alive, complete_gc, yield);
     }
+
+    // Cleaner references.  Included in timing for phantom references.  We
+    // expect Cleaner references to be temporary, and don't want to deal with
+    // possible incompatibilities arising from making it more visible.
+    for (uint i = 0; i < _max_num_q; i++) {
+      if (yield->should_return()) {
+        return;
+      }
+      preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive,
+                                  keep_alive, complete_gc, yield);
+    }
   }
 }
 
@@ -1375,6 +1398,7 @@
      case 1: return "WeakRef";
      case 2: return "FinalRef";
      case 3: return "PhantomRef";
+     case 4: return "CleanerRef";
    }
    ShouldNotReachHere();
    return NULL;
--- a/src/share/vm/memory/referenceProcessor.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/referenceProcessor.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -264,9 +264,10 @@
   DiscoveredList* _discoveredWeakRefs;
   DiscoveredList* _discoveredFinalRefs;
   DiscoveredList* _discoveredPhantomRefs;
+  DiscoveredList* _discoveredCleanerRefs;
 
  public:
-  static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); }
+  static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); }
 
   uint num_q()                             { return _num_q; }
   uint max_num_q()                         { return _max_num_q; }
--- a/src/share/vm/memory/referenceType.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/referenceType.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -35,7 +35,8 @@
   REF_SOFT,      // Subclass of java/lang/ref/SoftReference
   REF_WEAK,      // Subclass of java/lang/ref/WeakReference
   REF_FINAL,     // Subclass of java/lang/ref/FinalReference
-  REF_PHANTOM    // Subclass of java/lang/ref/PhantomReference
+  REF_PHANTOM,   // Subclass of java/lang/ref/PhantomReference
+  REF_CLEANER    // Subclass of sun/misc/Cleaner
 };
 
 #endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
--- a/src/share/vm/memory/sharedHeap.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/sharedHeap.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -32,7 +32,6 @@
 #include "runtime/atomic.inline.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/java.hpp"
-#include "services/management.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/workgroup.hpp"
 
@@ -40,33 +39,13 @@
 
 SharedHeap* SharedHeap::_sh;
 
-// The set of potentially parallel tasks in root scanning.
-enum SH_process_roots_tasks {
-  SH_PS_Universe_oops_do,
-  SH_PS_JNIHandles_oops_do,
-  SH_PS_ObjectSynchronizer_oops_do,
-  SH_PS_FlatProfiler_oops_do,
-  SH_PS_Management_oops_do,
-  SH_PS_SystemDictionary_oops_do,
-  SH_PS_ClassLoaderDataGraph_oops_do,
-  SH_PS_jvmti_oops_do,
-  SH_PS_CodeCache_oops_do,
-  // Leave this one last.
-  SH_PS_NumElements
-};
-
 SharedHeap::SharedHeap(CollectorPolicy* policy_) :
   CollectedHeap(),
   _collector_policy(policy_),
   _rem_set(NULL),
-  _strong_roots_scope(NULL),
   _strong_roots_parity(0),
-  _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)),
   _workers(NULL)
 {
-  if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
-    vm_exit_during_initialization("Failed necessary allocation.");
-  }
   _sh = this;  // ch is static, should be set only once.
   if ((UseParNewGC ||
       (UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled ||
@@ -84,14 +63,6 @@
   }
 }
 
-int SharedHeap::n_termination() {
-  return _process_strong_tasks->n_threads();
-}
-
-void SharedHeap::set_n_termination(int t) {
-  _process_strong_tasks->set_n_threads(t);
-}
-
 bool SharedHeap::heap_lock_held_for_gc() {
   Thread* t = Thread::current();
   return    Heap_lock->owned_by_self()
@@ -102,31 +73,6 @@
 void SharedHeap::set_par_threads(uint t) {
   assert(t == 0 || !UseSerialGC, "Cannot have parallel threads");
   _n_par_threads = t;
-  _process_strong_tasks->set_n_threads(t);
-}
-
-#ifdef ASSERT
-class AssertNonScavengableClosure: public OopClosure {
-public:
-  virtual void do_oop(oop* p) {
-    assert(!Universe::heap()->is_in_partial_collection(*p),
-      "Referent should not be scavengable.");  }
-  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
-};
-static AssertNonScavengableClosure assert_is_non_scavengable_closure;
-#endif
-
-SharedHeap::StrongRootsScope* SharedHeap::active_strong_roots_scope() const {
-  return _strong_roots_scope;
-}
-void SharedHeap::register_strong_roots_scope(SharedHeap::StrongRootsScope* scope) {
-  assert(_strong_roots_scope == NULL, "Should only have one StrongRootsScope active");
-  assert(scope != NULL, "Illegal argument");
-  _strong_roots_scope = scope;
-}
-void SharedHeap::unregister_strong_roots_scope(SharedHeap::StrongRootsScope* scope) {
-  assert(_strong_roots_scope == scope, "Wrong scope unregistered");
-  _strong_roots_scope = NULL;
 }
 
 void SharedHeap::change_strong_roots_parity() {
@@ -140,174 +86,15 @@
 }
 
 SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* heap, bool activate)
-  : MarkScope(activate), _sh(heap), _n_workers_done_with_threads(0)
+  : MarkScope(activate), _sh(heap)
 {
   if (_active) {
-    _sh->register_strong_roots_scope(this);
     _sh->change_strong_roots_parity();
     // Zero the claimed high water mark in the StringTable
     StringTable::clear_parallel_claimed_index();
   }
 }
 
-SharedHeap::StrongRootsScope::~StrongRootsScope() {
-  if (_active) {
-    _sh->unregister_strong_roots_scope(this);
-  }
-}
-
-Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false);
-
-void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) {
-  // The Thread work barrier is only needed by G1 Class Unloading.
-  // No need to use the barrier if this is single-threaded code.
-  if (UseG1GC && ClassUnloadingWithConcurrentMark && n_workers > 0) {
-    uint new_value = (uint)Atomic::add(1, &_n_workers_done_with_threads);
-    if (new_value == n_workers) {
-      // This thread is last. Notify the others.
-      MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
-      _lock->notify_all();
-    }
-  }
-}
-
-void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) {
-  assert(UseG1GC,                          "Currently only used by G1");
-  assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
-
-  // No need to use the barrier if this is single-threaded code.
-  if (n_workers > 0 && (uint)_n_workers_done_with_threads != n_workers) {
-    MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
-    while ((uint)_n_workers_done_with_threads != n_workers) {
-      _lock->wait(Mutex::_no_safepoint_check_flag, 0, false);
-    }
-  }
-}
-
-void SharedHeap::process_roots(bool activate_scope,
-                               ScanningOption so,
-                               OopClosure* strong_roots,
-                               OopClosure* weak_roots,
-                               CLDClosure* strong_cld_closure,
-                               CLDClosure* weak_cld_closure,
-                               CodeBlobClosure* code_roots) {
-  StrongRootsScope srs(this, activate_scope);
-
-  // General roots.
-  assert(_strong_roots_parity != 0, "must have called prologue code");
-  assert(code_roots != NULL, "code root closure should always be set");
-  // _n_termination for _process_strong_tasks should be set up stream
-  // in a method not running in a GC worker.  Otherwise the GC worker
-  // could be trying to change the termination condition while the task
-  // is executing in another GC worker.
-
-  // Iterating over the CLDG and the Threads are done early to allow G1 to
-  // first process the strong CLDs and nmethods and then, after a barrier,
-  // let the thread process the weak CLDs and nmethods.
-
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_ClassLoaderDataGraph_oops_do)) {
-    ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);
-  }
-
-  // Some CLDs contained in the thread frames should be considered strong.
-  // Don't process them if they will be processed during the ClassLoaderDataGraph phase.
-  CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
-  // Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway
-  CodeBlobClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
-
-  Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);
-
-  // This is the point where this worker thread will not find more strong CLDs/nmethods.
-  // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
-  active_strong_roots_scope()->mark_worker_done_with_threads(n_par_threads());
-
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) {
-    Universe::oops_do(strong_roots);
-  }
-  // Global (strong) JNI handles
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
-    JNIHandles::oops_do(strong_roots);
-
-  if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
-    ObjectSynchronizer::oops_do(strong_roots);
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
-    FlatProfiler::oops_do(strong_roots);
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_Management_oops_do))
-    Management::oops_do(strong_roots);
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_jvmti_oops_do))
-    JvmtiExport::oops_do(strong_roots);
-
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_SystemDictionary_oops_do)) {
-    SystemDictionary::roots_oops_do(strong_roots, weak_roots);
-  }
-
-  // All threads execute the following. A specific chunk of buckets
-  // from the StringTable are the individual tasks.
-  if (weak_roots != NULL) {
-    if (CollectedHeap::use_parallel_gc_threads()) {
-      StringTable::possibly_parallel_oops_do(weak_roots);
-    } else {
-      StringTable::oops_do(weak_roots);
-    }
-  }
-
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
-    if (so & SO_ScavengeCodeCache) {
-      assert(code_roots != NULL, "must supply closure for code cache");
-
-      // We only visit parts of the CodeCache when scavenging.
-      CodeCache::scavenge_root_nmethods_do(code_roots);
-    }
-    if (so & SO_AllCodeCache) {
-      assert(code_roots != NULL, "must supply closure for code cache");
-
-      // CMSCollector uses this to do intermediate-strength collections.
-      // We scan the entire code cache, since CodeCache::do_unloading is not called.
-      CodeCache::blobs_do(code_roots);
-    }
-    // Verify that the code cache contents are not subject to
-    // movement by a scavenging collection.
-    DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations));
-    DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
-  }
-
-  _process_strong_tasks->all_tasks_completed();
-}
-
-void SharedHeap::process_all_roots(bool activate_scope,
-                                   ScanningOption so,
-                                   OopClosure* roots,
-                                   CLDClosure* cld_closure,
-                                   CodeBlobClosure* code_closure) {
-  process_roots(activate_scope, so,
-                roots, roots,
-                cld_closure, cld_closure,
-                code_closure);
-}
-
-void SharedHeap::process_strong_roots(bool activate_scope,
-                                      ScanningOption so,
-                                      OopClosure* roots,
-                                      CLDClosure* cld_closure,
-                                      CodeBlobClosure* code_closure) {
-  process_roots(activate_scope, so,
-                roots, NULL,
-                cld_closure, NULL,
-                code_closure);
-}
-
-
-class AlwaysTrueClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop p) { return true; }
-};
-static AlwaysTrueClosure always_true;
-
-void SharedHeap::process_weak_roots(OopClosure* root_closure) {
-  // Global (weak) JNI handles
-  JNIHandles::weak_oops_do(&always_true, root_closure);
-}
-
 void SharedHeap::set_barrier_set(BarrierSet* bs) {
   _barrier_set = bs;
   // Cached barrier set for fast access in oops
--- a/src/share/vm/memory/sharedHeap.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/sharedHeap.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -61,18 +61,18 @@
 //    counts the number of tasks that have been done and then reset
 //    the SubTasksDone so that it can be used again.  When the number of
 //    tasks is set to the number of GC workers, then _n_threads must
-//    be set to the number of active GC workers. G1CollectedHeap,
-//    HRInto_G1RemSet, GenCollectedHeap and SharedHeap have SubTasksDone.
-//    This seems too many.
+//    be set to the number of active GC workers. G1RootProcessor and
+//    GenCollectedHeap have SubTasksDone.
 //    3) SequentialSubTasksDone has an _n_threads that is used in
 //    a way similar to SubTasksDone and has the same dependency on the
 //    number of active GC workers.  CompactibleFreeListSpace and Space
 //    have SequentialSubTasksDone's.
-// Example of using SubTasksDone and SequentialSubTasksDone
-// G1CollectedHeap::g1_process_roots()
-//  to SharedHeap::process_roots() and uses
-//  SubTasksDone* _process_strong_tasks to claim tasks.
-//  process_roots() calls
+//
+// Examples of using SubTasksDone and SequentialSubTasksDone:
+//  G1RootProcessor and GenCollectedHeap::process_roots() use
+//  SubTasksDone* _process_strong_tasks to claim tasks for workers
+//
+//  GenCollectedHeap::gen_process_roots() calls
 //      rem_set()->younger_refs_iterate()
 //  to scan the card table and which eventually calls down into
 //  CardTableModRefBS::par_non_clean_card_iterate_work().  This method
@@ -104,10 +104,6 @@
   friend class VM_GC_Operation;
   friend class VM_CGC_Operation;
 
-private:
-  // For claiming strong_roots tasks.
-  SubTasksDone* _process_strong_tasks;
-
 protected:
   // There should be only a single instance of "SharedHeap" in a program.
   // This is enforced with the protected constructor below, which will also
@@ -144,7 +140,6 @@
   static SharedHeap* heap() { return _sh; }
 
   void set_barrier_set(BarrierSet* bs);
-  SubTasksDone* process_strong_tasks() { return _process_strong_tasks; }
 
   // Does operations required after initialization has been done.
   virtual void post_initialize();
@@ -201,69 +196,19 @@
   // strong_roots_prologue calls change_strong_roots_parity, if
   // parallel tasks are enabled.
   class StrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
-    // Used to implement the Thread work barrier.
-    static Monitor* _lock;
-
     SharedHeap*   _sh;
-    volatile jint _n_workers_done_with_threads;
 
    public:
     StrongRootsScope(SharedHeap* heap, bool activate = true);
-    ~StrongRootsScope();
-
-    // Mark that this thread is done with the Threads work.
-    void mark_worker_done_with_threads(uint n_workers);
-    // Wait until all n_workers are done with the Threads work.
-    void wait_until_all_workers_done_with_threads(uint n_workers);
   };
   friend class StrongRootsScope;
 
-  // The current active StrongRootScope
-  StrongRootsScope* _strong_roots_scope;
-
-  StrongRootsScope* active_strong_roots_scope() const;
-
  private:
-  void register_strong_roots_scope(StrongRootsScope* scope);
-  void unregister_strong_roots_scope(StrongRootsScope* scope);
   void change_strong_roots_parity();
 
  public:
-  enum ScanningOption {
-    SO_None                =  0x0,
-    SO_AllCodeCache        =  0x8,
-    SO_ScavengeCodeCache   = 0x10
-  };
-
   FlexibleWorkGang* workers() const { return _workers; }
 
-  // Invoke the "do_oop" method the closure "roots" on all root locations.
-  // The "so" argument determines which roots the closure is applied to:
-  // "SO_None" does none;
-  // "SO_AllCodeCache" applies the closure to all elements of the CodeCache.
-  // "SO_ScavengeCodeCache" applies the closure to elements on the scavenge root list in the CodeCache.
-  void process_roots(bool activate_scope,
-                     ScanningOption so,
-                     OopClosure* strong_roots,
-                     OopClosure* weak_roots,
-                     CLDClosure* strong_cld_closure,
-                     CLDClosure* weak_cld_closure,
-                     CodeBlobClosure* code_roots);
-  void process_all_roots(bool activate_scope,
-                         ScanningOption so,
-                         OopClosure* roots,
-                         CLDClosure* cld_closure,
-                         CodeBlobClosure* code_roots);
-  void process_strong_roots(bool activate_scope,
-                            ScanningOption so,
-                            OopClosure* roots,
-                            CLDClosure* cld_closure,
-                            CodeBlobClosure* code_roots);
-
-
-  // Apply "root_closure" to the JNI weak roots..
-  void process_weak_roots(OopClosure* root_closure);
-
   // The functions below are helper functions that a subclass of
   // "SharedHeap" can use in the implementation of its virtual
   // functions.
@@ -278,9 +223,6 @@
   // (such as process roots) subsequently.
   virtual void set_par_threads(uint t);
 
-  int n_termination();
-  void set_n_termination(int t);
-
   //
   // New methods from CollectedHeap
   //
@@ -292,8 +234,4 @@
                              size_t capacity);
 };
 
-inline SharedHeap::ScanningOption operator|(SharedHeap::ScanningOption so0, SharedHeap::ScanningOption so1) {
-  return static_cast<SharedHeap::ScanningOption>(static_cast<int>(so0) | static_cast<int>(so1));
-}
-
 #endif // SHARE_VM_MEMORY_SHAREDHEAP_HPP
--- a/src/share/vm/memory/tenuredGeneration.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,6 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/shared/collectorCounters.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/blockOffsetTable.inline.hpp"
 #include "memory/generation.inline.hpp"
@@ -34,6 +33,9 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#endif
 
 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
                                      size_t initial_byte_size, int level,
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -235,22 +235,19 @@
 }
 
 size_t ThreadLocalAllocBuffer::initial_desired_size() {
-  size_t init_sz;
+  size_t init_sz = 0;
 
   if (TLABSize > 0) {
-    init_sz = MIN2(TLABSize / HeapWordSize, max_size());
-  } else if (global_stats() == NULL) {
-    // Startup issue - main thread initialized before heap initialized.
-    init_sz = min_size();
-  } else {
+    init_sz = TLABSize / HeapWordSize;
+  } else if (global_stats() != NULL) {
     // Initial size is a function of the average number of allocating threads.
     unsigned nof_threads = global_stats()->allocating_threads_avg();
 
     init_sz  = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
                       (nof_threads * target_refills());
     init_sz = align_object_size(init_sz);
-    init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
   }
+  init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
   return init_sz;
 }
 
--- a/src/share/vm/memory/threadLocalAllocBuffer.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -105,7 +105,7 @@
     // do nothing.  tlabs must be inited by initialize() calls
   }
 
-  static const size_t min_size()                 { return align_object_size(MinTLABSize / HeapWordSize); }
+  static const size_t min_size()                 { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); }
   static const size_t max_size()                 { assert(_max_size != 0, "max_size not set up"); return _max_size; }
   static void set_max_size(size_t max_size)      { _max_size = max_size; }
 
--- a/src/share/vm/oops/constMethod.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/constMethod.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,6 +222,7 @@
   u2                _max_stack;                  // Maximum number of entries on the expression stack
   u2                _max_locals;                 // Number of local variables used by this method
   u2                _size_of_parameters;         // size of the parameter block (receiver + arguments) in words
+  u2                _orig_method_idnum;          // Original unique identification number for the method
 
   // Constructor
   ConstMethod(int byte_code_size,
@@ -475,6 +476,9 @@
   u2 method_idnum() const                        { return _method_idnum; }
   void set_method_idnum(u2 idnum)                { _method_idnum = idnum; }
 
+  u2 orig_method_idnum() const                   { return _orig_method_idnum; }
+  void set_orig_method_idnum(u2 idnum)           { _orig_method_idnum = idnum; }
+
   // max stack
   int  max_stack() const                         { return _max_stack; }
   void set_max_stack(int size)                   { _max_stack = size; }
--- a/src/share/vm/oops/cpCache.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/cpCache.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -449,7 +449,6 @@
           new_method->name()->as_C_string(),
           new_method->signature()->as_C_string()));
       }
-
       return true;
     }
 
@@ -477,7 +476,6 @@
         new_method->name()->as_C_string(),
         new_method->signature()->as_C_string()));
     }
-
     return true;
   }
 
@@ -498,41 +496,39 @@
     // _f1 == NULL || !_f1->is_method() are OK here
     return true;
   }
-  // return false if _f1 refers to an old or an obsolete method
+  // return false if _f1 refers to a non-deleted old or obsolete method
   return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
-          !((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
+          (f1_as_method()->is_deleted() ||
+          (!f1_as_method()->is_old() && !f1_as_method()->is_obsolete())));
 }
 
-bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
+Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
   if (!is_method_entry()) {
     // not a method entry so not interesting by default
-    return false;
+    return NULL;
   }
-
   Method* m = NULL;
   if (is_vfinal()) {
     // virtual and final so _f2 contains method ptr instead of vtable index
     m = f2_as_vfinal_method();
   } else if (is_f1_null()) {
     // NULL _f1 means this is a virtual entry so also not interesting
-    return false;
+    return NULL;
   } else {
     if (!(_f1->is_method())) {
       // _f1 can also contain a Klass* for an interface
-      return false;
+      return NULL;
     }
     m = f1_as_method();
   }
-
   assert(m != NULL && m->is_method(), "sanity check");
   if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
     // robustness for above sanity checks or method is not in
     // the interesting class
-    return false;
+    return NULL;
   }
-
   // the method is in the interesting class so the entry is interesting
-  return true;
+  return m;
 }
 #endif // INCLUDE_JVMTI
 
@@ -609,7 +605,7 @@
 // If any entry of this ConstantPoolCache points to any of
 // old_methods, replace it with the corresponding new_method.
 void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
-                                                     int methods_length, bool * trace_name_printed) {
+                                              int methods_length, bool * trace_name_printed) {
 
   if (methods_length == 0) {
     // nothing to do if there are no methods
@@ -620,7 +616,7 @@
   Klass* old_holder = old_methods[0]->method_holder();
 
   for (int i = 0; i < length(); i++) {
-    if (!entry_at(i)->is_interesting_method_entry(old_holder)) {
+    if (entry_at(i)->get_interesting_method_entry(old_holder) == NULL) {
       // skip uninteresting methods
       continue;
     }
@@ -644,10 +640,33 @@
   }
 }
 
+// If any entry of this ConstantPoolCache points to any of
+// old_methods, replace it with the corresponding new_method.
+void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
+  for (int i = 0; i < length(); i++) {
+    ConstantPoolCacheEntry* entry = entry_at(i);
+    Method* old_method = entry->get_interesting_method_entry(holder);
+    if (old_method == NULL || !old_method->is_old()) {
+      continue; // skip uninteresting entries
+    }
+    if (old_method->is_deleted()) {
+      // clean up entries with deleted methods
+      entry->initialize_entry(entry->constant_pool_index());
+      continue;
+    }
+    Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
+
+    assert(new_method != NULL, "method_with_idnum() should not be NULL");
+    assert(old_method != new_method, "sanity check");
+
+    entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed);
+  }
+}
+
 // the constant pool cache should never contain old or obsolete methods
 bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
   for (int i = 1; i < length(); i++) {
-    if (entry_at(i)->is_interesting_method_entry(NULL) &&
+    if (entry_at(i)->get_interesting_method_entry(NULL) != NULL &&
         !entry_at(i)->check_no_old_or_obsolete_entries()) {
       return false;
     }
@@ -657,7 +676,7 @@
 
 void ConstantPoolCache::dump_cache() {
   for (int i = 1; i < length(); i++) {
-    if (entry_at(i)->is_interesting_method_entry(NULL)) {
+    if (entry_at(i)->get_interesting_method_entry(NULL) != NULL) {
       entry_at(i)->print(tty, i);
     }
   }
--- a/src/share/vm/oops/cpCache.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/cpCache.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -378,9 +378,9 @@
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
   bool adjust_method_entry(Method* old_method, Method* new_method,
-         bool * trace_name_printed);
+         bool* trace_name_printed);
   bool check_no_old_or_obsolete_entries();
-  bool is_interesting_method_entry(Klass* k);
+  Method* get_interesting_method_entry(Klass* k);
 #endif // INCLUDE_JVMTI
 
   // Debugging & Printing
@@ -477,7 +477,8 @@
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
-                             int methods_length, bool * trace_name_printed);
+                             int methods_length, bool* trace_name_printed);
+  void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed);
   bool check_no_old_or_obsolete_entries();
   void dump_cache();
 #endif // INCLUDE_JVMTI
--- a/src/share/vm/oops/instanceKlass.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,7 +110,7 @@
       len = name->utf8_length();                                 \
     }                                                            \
     HS_DTRACE_PROBE4(hotspot, class__initialization__##type,     \
-      data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type);           \
+      data, len, (void *)(clss)->class_loader(), thread_type);           \
   }
 
 #define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
@@ -123,7 +123,7 @@
       len = name->utf8_length();                                 \
     }                                                            \
     HS_DTRACE_PROBE5(hotspot, class__initialization__##type,     \
-      data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type, wait);     \
+      data, len, (void *)(clss)->class_loader(), thread_type, wait);     \
   }
 #else /* USDT2 */
 
@@ -1453,32 +1453,41 @@
 }
 
 Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const {
-  return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass);
+  return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false);
 }
 
 // find_instance_method looks up the name/signature in the local methods array
 // and skips over static methods
 Method* InstanceKlass::find_instance_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
-  Method* meth = InstanceKlass::find_method(methods, name, signature);
-  if (meth != NULL && meth->is_static()) {
-      meth = NULL;
-  }
+  Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true);
   return meth;
 }
 
+// find_instance_method looks up the name/signature in the local methods array
+// and skips over static methods
+Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
+    return InstanceKlass::find_instance_method(methods(), name, signature);
+}
+
 // find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
-  return InstanceKlass::find_method_impl(methods, name, signature, false);
+  return InstanceKlass::find_method_impl(methods, name, signature, false, false);
 }
 
 Method* InstanceKlass::find_method_impl(
-    Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
-  int hit = find_method_index(methods, name, signature, skipping_overpass);
+    Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+  int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static);
   return hit >= 0 ? methods->at(hit): NULL;
 }
 
+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+    return (m->signature() == signature) &&
+            (!skipping_overpass || !m->is_overpass()) &&
+            (!skipping_static || !m->is_static());
+}
+
 // Used directly for default_methods to find the index into the
 // default_vtable_indices, and indirectly by find_method
 // find_method_index looks in the local methods array to return the index
@@ -1487,13 +1496,14 @@
 // is important during method resolution to prefer a static method, for example,
 // over an overpass method.
 int InstanceKlass::find_method_index(
-    Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
+    Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
   int hit = binary_search(methods, name);
   if (hit != -1) {
     Method* m = methods->at(hit);
+
     // Do linear search to find matching signature.  First, quick check
     // for common case, ignoring overpasses if requested.
-    if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit;
+    if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit;
 
     // search downwards through overloaded methods
     int i;
@@ -1501,18 +1511,18 @@
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
+        if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
     }
     // search upwards
     for (i = hit + 1; i < methods->length(); ++i) {
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
+        if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
     }
     // not found
 #ifdef ASSERT
-    int index = skipping_overpass ? -1 : linear_search(methods, name, signature);
+    int index = skipping_overpass || skipping_static ? -1 : linear_search(methods, name, signature);
     assert(index == -1, err_msg("binary search should have found entry %d", index));
 #endif
   }
@@ -2788,30 +2798,33 @@
 // not yet in the vtable due to concurrent subclass define and superinterface
 // redefinition
 // Note: those in the vtable, should have been updated via adjust_method_entries
-void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods,
-                                           int methods_length, bool* trace_name_printed) {
+void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) {
   // search the default_methods for uses of either obsolete or EMCP methods
   if (default_methods() != NULL) {
-    for (int j = 0; j < methods_length; j++) {
-      Method* old_method = old_methods[j];
-      Method* new_method = new_methods[j];
-
-      for (int index = 0; index < default_methods()->length(); index ++) {
-        if (default_methods()->at(index) == old_method) {
-          default_methods()->at_put(index, new_method);
-          if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
-            if (!(*trace_name_printed)) {
-              // RC_TRACE_MESG macro has an embedded ResourceMark
-              RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
-                             external_name(),
-                             old_method->method_holder()->external_name()));
-              *trace_name_printed = true;
-            }
-            RC_TRACE(0x00100000, ("default method update: %s(%s) ",
-                                  new_method->name()->as_C_string(),
-                                  new_method->signature()->as_C_string()));
-          }
+    for (int index = 0; index < default_methods()->length(); index ++) {
+      Method* old_method = default_methods()->at(index);
+      if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
+        continue; // skip uninteresting entries
+      }
+      assert(!old_method->is_deleted(), "default methods may not be deleted");
+
+      Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
+
+      assert(new_method != NULL, "method_with_idnum() should not be NULL");
+      assert(old_method != new_method, "sanity check");
+
+      default_methods()->at_put(index, new_method);
+      if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
+        if (!(*trace_name_printed)) {
+          // RC_TRACE_MESG macro has an embedded ResourceMark
+          RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
+                         external_name(),
+                         old_method->method_holder()->external_name()));
+          *trace_name_printed = true;
         }
+        RC_TRACE(0x00100000, ("default method update: %s(%s) ",
+                              new_method->name()->as_C_string(),
+                              new_method->signature()->as_C_string()));
       }
     }
   }
@@ -3734,6 +3747,22 @@
 } // end has_previous_version()
 
 
+InstanceKlass* InstanceKlass::get_klass_version(int version) {
+  if (constants()->version() == version) {
+    return this;
+  }
+  PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
+  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
+       pv_node != NULL; pv_node = pvw.next_previous_version()) {
+    ConstantPool* prev_cp = pv_node->prev_constant_pool();
+    if (prev_cp->version() == version) {
+      return prev_cp->pool_holder();
+    }
+  }
+  return NULL; // None found
+}
+
+
 Method* InstanceKlass::method_with_idnum(int idnum) {
   Method* m = NULL;
   if (idnum < methods()->length()) {
@@ -3752,6 +3781,37 @@
   return m;
 }
 
+
+Method* InstanceKlass::method_with_orig_idnum(int idnum) {
+  if (idnum >= methods()->length()) {
+    return NULL;
+  }
+  Method* m = methods()->at(idnum);
+  if (m != NULL && m->orig_method_idnum() == idnum) {
+    return m;
+  }
+  // Obsolete method idnum does not match the original idnum
+  for (int index = 0; index < methods()->length(); ++index) {
+    m = methods()->at(index);
+    if (m->orig_method_idnum() == idnum) {
+      return m;
+    }
+  }
+  // None found, return null for the caller to handle.
+  return NULL;
+}
+
+
+Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
+  InstanceKlass* holder = get_klass_version(version);
+  if (holder == NULL) {
+    return NULL; // The version of klass is gone, no method is found
+  }
+  Method* method = holder->method_with_orig_idnum(idnum);
+  return method;
+}
+
+
 jint InstanceKlass::get_cached_class_file_len() {
   return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
 }
--- a/src/share/vm/oops/instanceKlass.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -358,6 +358,8 @@
   Array<Method*>* methods() const          { return _methods; }
   void set_methods(Array<Method*>* a)      { _methods = a; }
   Method* method_with_idnum(int idnum);
+  Method* method_with_orig_idnum(int idnum);
+  Method* method_with_orig_idnum(int idnum, int version);
 
   // method ordering
   Array<int>* method_ordering() const     { return _method_ordering; }
@@ -520,10 +522,16 @@
   // find a local method (returns NULL if not found)
   Method* find_method(Symbol* name, Symbol* signature) const;
   static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+
+  // find a local method, but skip static methods
+  Method* find_instance_method(Symbol* name, Symbol* signature);
   static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
 
+  // true if method matches signature and conforms to skipping_X conditions.
+  static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
+
   // find a local method index in default_methods (returns -1 if not found)
-  static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+  static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
 
   // lookup operation (returns NULL if not found)
   Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
@@ -652,6 +660,7 @@
     return _previous_versions;
   }
 
+  InstanceKlass* get_klass_version(int version);
   static void purge_previous_versions(InstanceKlass* ik);
 
   // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
@@ -953,8 +962,7 @@
   Method* method_at_itable(Klass* holder, int index, TRAPS);
 
 #if INCLUDE_JVMTI
-  void adjust_default_methods(Method** old_methods, Method** new_methods,
-                              int methods_length, bool* trace_name_printed);
+  void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
 #endif // INCLUDE_JVMTI
 
   // Garbage collection
@@ -1076,7 +1084,7 @@
 
   // find a local method (returns NULL if not found)
   Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const;
-  static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+  static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
 
   // Free CHeap allocated fields.
   void release_C_heap_structures();
--- a/src/share/vm/oops/klassVtable.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/klassVtable.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -401,13 +401,15 @@
       // get super_klass for method_holder for the found method
       InstanceKlass* super_klass =  super_method->method_holder();
 
-      if (is_default
+      // private methods are also never overridden
+      if (!super_method->is_private() &&
+          (is_default
           || ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
           || ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
           && ((super_klass = find_transitive_override(super_klass,
                              target_method, i, target_loader,
                              target_classname, THREAD))
-                             != (InstanceKlass*)NULL))))
+                             != (InstanceKlass*)NULL)))))
         {
         // Package private methods always need a new entry to root their own
         // overriding. They may also override other methods.
@@ -689,9 +691,15 @@
 // check if a method is a miranda method, given a class's methods table,
 // its default_method table  and its super
 // Miranda methods are calculated twice:
-// first: before vtable size calculation: including abstract and default
+// first: before vtable size calculation: including abstract and superinterface default
+// We include potential default methods to give them space in the vtable.
+// During the first run, the default_methods list is empty
 // This is seen by default method creation
-// Second: recalculated during vtable initialization: only abstract
+// Second: recalculated during vtable initialization: only include abstract methods.
+// During the second run, default_methods is set up, so concrete methods from
+// superinterfaces with matching names/signatures to default_methods are already
+// in the default_methods list and do not need to be appended to the vtable
+// as mirandas
 // This is seen by link resolution and selection.
 // "miranda" means not static, not defined by this class.
 // private methods in interfaces do not belong in the miranda list.
@@ -706,8 +714,9 @@
   }
   Symbol* name = m->name();
   Symbol* signature = m->signature();
+  Method* mo;
 
-  if (InstanceKlass::find_instance_method(class_methods, name, signature) == NULL) {
+  if ((mo = InstanceKlass::find_instance_method(class_methods, name, signature)) == NULL) {
     // did not find it in the method table of the current class
     if ((default_methods == NULL) ||
         InstanceKlass::find_method(default_methods, name, signature) == NULL) {
@@ -716,7 +725,7 @@
         return true;
       }
 
-      Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
+      mo = InstanceKlass::cast(super)->lookup_method(name, signature);
       while (mo != NULL && mo->access_flags().is_static()
              && mo->method_holder() != NULL
              && mo->method_holder()->super() != NULL)
@@ -728,6 +737,18 @@
         return true;
       }
     }
+  } else {
+     // if the local class has a private method, the miranda will not
+     // override it, so a vtable slot is needed
+     if (mo->access_flags().is_private()) {
+
+       // Second round, weed out any superinterface methods that turned
+       // into default methods, i.e. were concrete not abstract in the end
+       if ((default_methods == NULL) ||
+         InstanceKlass::find_method(default_methods, name, signature) == NULL) {
+         return true;
+       }
+    }
   }
 
   return false;
@@ -860,44 +881,43 @@
   }
   return updated;
 }
-void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
-                                        int methods_length, bool * trace_name_printed) {
-  // search the vtable for uses of either obsolete or EMCP methods
-  for (int j = 0; j < methods_length; j++) {
-    Method* old_method = old_methods[j];
-    Method* new_method = new_methods[j];
+
+// search the vtable for uses of either obsolete or EMCP methods
+void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
+  int prn_enabled = 0;
+  for (int index = 0; index < length(); index++) {
+    Method* old_method = unchecked_method_at(index);
+    if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
+      continue; // skip uninteresting entries
+    }
+    assert(!old_method->is_deleted(), "vtable methods may not be deleted");
+
+    Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
+
+    assert(new_method != NULL, "method_with_idnum() should not be NULL");
+    assert(old_method != new_method, "sanity check");
 
-    // In the vast majority of cases we could get the vtable index
-    // by using:  old_method->vtable_index()
-    // However, there are rare cases, eg. sun.awt.X11.XDecoratedPeer.getX()
-    // in sun.awt.X11.XFramePeer where methods occur more than once in the
-    // vtable, so, alas, we must do an exhaustive search.
-    for (int index = 0; index < length(); index++) {
-      if (unchecked_method_at(index) == old_method) {
-        put_method_at(new_method, index);
-          // For default methods, need to update the _default_methods array
-          // which can only have one method entry for a given signature
-          bool updated_default = false;
-          if (old_method->is_default_method()) {
-            updated_default = adjust_default_method(index, old_method, new_method);
-          }
+    put_method_at(new_method, index);
+    // For default methods, need to update the _default_methods array
+    // which can only have one method entry for a given signature
+    bool updated_default = false;
+    if (old_method->is_default_method()) {
+      updated_default = adjust_default_method(index, old_method, new_method);
+    }
 
-        if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
-          if (!(*trace_name_printed)) {
-            // RC_TRACE_MESG macro has an embedded ResourceMark
-            RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
-                           klass()->external_name(),
-                           old_method->method_holder()->external_name()));
-            *trace_name_printed = true;
-          }
-          // RC_TRACE macro has an embedded ResourceMark
-          RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
-                                new_method->name()->as_C_string(),
-                                new_method->signature()->as_C_string(),
-                                updated_default ? "true" : "false"));
-        }
-        // cannot 'break' here; see for-loop comment above.
+    if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
+      if (!(*trace_name_printed)) {
+        // RC_TRACE_MESG macro has an embedded ResourceMark
+        RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
+                       klass()->external_name(),
+                       old_method->method_holder()->external_name()));
+        *trace_name_printed = true;
       }
+      // RC_TRACE macro has an embedded ResourceMark
+      RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
+                            new_method->name()->as_C_string(),
+                            new_method->signature()->as_C_string(),
+                            updated_default ? "true" : "false"));
     }
   }
 }
@@ -1190,37 +1210,35 @@
 }
 
 #if INCLUDE_JVMTI
-void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
-                                        int methods_length, bool * trace_name_printed) {
-  // search the itable for uses of either obsolete or EMCP methods
-  for (int j = 0; j < methods_length; j++) {
-    Method* old_method = old_methods[j];
-    Method* new_method = new_methods[j];
-    itableMethodEntry* ime = method_entry(0);
+// search the itable for uses of either obsolete or EMCP methods
+void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
 
-    // The itable can describe more than one interface and the same
-    // method signature can be specified by more than one interface.
-    // This means we have to do an exhaustive search to find all the
-    // old_method references.
-    for (int i = 0; i < _size_method_table; i++) {
-      if (ime->method() == old_method) {
-        ime->initialize(new_method);
+  itableMethodEntry* ime = method_entry(0);
+  for (int i = 0; i < _size_method_table; i++, ime++) {
+    Method* old_method = ime->method();
+    if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
+      continue; // skip uninteresting entries
+    }
+    assert(!old_method->is_deleted(), "itable methods may not be deleted");
+
+    Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
 
-        if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
-          if (!(*trace_name_printed)) {
-            // RC_TRACE_MESG macro has an embedded ResourceMark
-            RC_TRACE_MESG(("adjust: name=%s",
-              old_method->method_holder()->external_name()));
-            *trace_name_printed = true;
-          }
-          // RC_TRACE macro has an embedded ResourceMark
-          RC_TRACE(0x00200000, ("itable method update: %s(%s)",
-            new_method->name()->as_C_string(),
-            new_method->signature()->as_C_string()));
-        }
-        // cannot 'break' here; see for-loop comment above.
+    assert(new_method != NULL, "method_with_idnum() should not be NULL");
+    assert(old_method != new_method, "sanity check");
+
+    ime->initialize(new_method);
+
+    if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
+      if (!(*trace_name_printed)) {
+        // RC_TRACE_MESG macro has an embedded ResourceMark
+        RC_TRACE_MESG(("adjust: name=%s",
+          old_method->method_holder()->external_name()));
+        *trace_name_printed = true;
       }
-      ime++;
+      // RC_TRACE macro has an embedded ResourceMark
+      RC_TRACE(0x00200000, ("itable method update: %s(%s)",
+        new_method->name()->as_C_string(),
+        new_method->signature()->as_C_string()));
     }
   }
 }
--- a/src/share/vm/oops/klassVtable.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/klassVtable.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,8 +98,7 @@
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
   bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method);
-  void adjust_method_entries(Method** old_methods, Method** new_methods,
-                             int methods_length, bool * trace_name_printed);
+  void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
   bool check_no_old_or_obsolete_entries();
   void dump_vtable();
 #endif // INCLUDE_JVMTI
@@ -288,8 +287,7 @@
   // trace_name_printed is set to true if the current call has
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
-  void adjust_method_entries(Method** old_methods, Method** new_methods,
-                             int methods_length, bool * trace_name_printed);
+  void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
   bool check_no_old_or_obsolete_entries();
   void dump_itable();
 #endif // INCLUDE_JVMTI
--- a/src/share/vm/oops/markOop.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/markOop.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,17 +25,40 @@
 #include "precompiled.hpp"
 #include "oops/markOop.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/objectMonitor.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
 void markOopDesc::print_on(outputStream* st) const {
-  if (is_locked()) {
-    st->print("locked(" INTPTR_FORMAT ")->", value());
-    markOop(*(markOop*)value())->print_on(st);
+  if (is_marked()) {
+    st->print(" marked(" INTPTR_FORMAT ")", value());
+  } else if (is_locked()) {
+    st->print(" locked(" INTPTR_FORMAT ")->", value());
+    if (is_neutral()) {
+      st->print("is_neutral");
+      if (has_no_hash()) st->print(" no_hash");
+      else st->print(" hash=" INTPTR_FORMAT, hash());
+      st->print(" age=%d", age());
+    } else if (has_bias_pattern()) {
+      st->print("is_biased");
+      JavaThread* jt = biased_locker();
+      st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
+    } else if (has_monitor()) {
+      ObjectMonitor* mon = monitor();
+      if (mon == NULL)
+        st->print("monitor=NULL");
+      else {
+        BasicLock * bl = (BasicLock *) mon->owner();
+        st->print("monitor={count="INTPTR_FORMAT",waiters="INTPTR_FORMAT",recursions="INTPTR_FORMAT",owner="INTPTR_FORMAT"}",
+                mon->count(), mon->waiters(), mon->recursions(), p2i(bl));
+      }
+    } else {
+      st->print("??");
+    }
   } else {
     assert(is_unlocked() || has_bias_pattern(), "just checking");
     st->print("mark(");
-    if (has_bias_pattern())  st->print("biased,");
+    if (has_bias_pattern()) st->print("biased,");
     st->print("hash %#lx,", hash());
     st->print("age %d)", age());
   }
--- a/src/share/vm/oops/method.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/method.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1419,6 +1419,7 @@
       for (int i = 0; i < length; i++) {
         Method* m = methods->at(i);
         m->set_method_idnum(i);
+        m->set_orig_method_idnum(i);
       }
     }
   }
--- a/src/share/vm/oops/method.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/oops/method.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -265,6 +265,9 @@
   u2 method_idnum() const           { return constMethod()->method_idnum(); }
   void set_method_idnum(u2 idnum)   { constMethod()->set_method_idnum(idnum); }
 
+  u2 orig_method_idnum() const           { return constMethod()->orig_method_idnum(); }
+  void set_orig_method_idnum(u2 idnum)   { constMethod()->set_orig_method_idnum(idnum); }
+
   // code size
   int code_size() const                  { return constMethod()->code_size(); }
 
@@ -714,6 +717,8 @@
   void set_is_old()                                 { _access_flags.set_is_old(); }
   bool is_obsolete() const                          { return access_flags().is_obsolete(); }
   void set_is_obsolete()                            { _access_flags.set_is_obsolete(); }
+  bool is_deleted() const                           { return access_flags().is_deleted(); }
+  void set_is_deleted()                             { _access_flags.set_is_deleted(); }
   bool on_stack() const                             { return access_flags().on_stack(); }
   void set_on_stack(const bool value);
 
--- a/src/share/vm/opto/c2compiler.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/c2compiler.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +25,17 @@
 #include "precompiled.hpp"
 #include "opto/c2compiler.hpp"
 #include "opto/runtime.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/callnode.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/callnode.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "compiler/compileLog.hpp"
 #include "ci/bcEscapeAnalyzer.hpp"
 #include "compiler/oopMap.hpp"
 #include "opto/callGenerator.hpp"
@@ -1670,6 +1671,9 @@
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
       // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+      this->log_lock_optimization(phase->C,"eliminate_lock_set_non_esc1");
+#endif
       this->set_non_esc_obj();
       return result;
     }
@@ -1731,6 +1735,9 @@
           AbstractLockNode* lock = lock_ops.at(i);
 
           // Mark it eliminated by coarsening and update any counters
+#ifdef ASSERT
+          lock->log_lock_optimization(phase->C, "eliminate_lock_set_coarsened");
+#endif
           lock->set_coarsened();
         }
       } else if (ctrl->is_Region() &&
@@ -1749,16 +1756,33 @@
 
 //=============================================================================
 bool LockNode::is_nested_lock_region() {
+  return is_nested_lock_region(NULL);
+}
+
+// p is used for access to compilation log; no logging if NULL
+bool LockNode::is_nested_lock_region(Compile * c) {
   BoxLockNode* box = box_node()->as_BoxLock();
   int stk_slot = box->stack_slot();
-  if (stk_slot <= 0)
+  if (stk_slot <= 0) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_1");
+#endif
     return false; // External lock or it is not Box (Phi node).
+  }
 
   // Ignore complex cases: merged locks or multiple locks.
   Node* obj = obj_node();
   LockNode* unique_lock = NULL;
-  if (!box->is_simple_lock_region(&unique_lock, obj) ||
-      (unique_lock != this)) {
+  if (!box->is_simple_lock_region(&unique_lock, obj)) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_2a");
+#endif
+    return false;
+  }
+  if (unique_lock != this) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_2b");
+#endif
     return false;
   }
 
@@ -1778,6 +1802,9 @@
       }
     }
   }
+#ifdef ASSERT
+  this->log_lock_optimization(c, "eliminate_lock_INLR_3");
+#endif
   return false;
 }
 
@@ -1809,8 +1836,40 @@
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
       // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+      this->log_lock_optimization(phase->C, "eliminate_lock_set_non_esc2");
+#endif
       this->set_non_esc_obj();
     }
   }
   return result;
 }
+
+const char * AbstractLockNode::kind_as_string() const {
+  return is_coarsened()   ? "coarsened" :
+         is_nested()      ? "nested" :
+         is_non_esc_obj() ? "non_escaping" :
+         "?";
+}
+
+void AbstractLockNode::log_lock_optimization(Compile *C, const char * tag)  const {
+  if (C == NULL) {
+    return;
+  }
+  CompileLog* log = C->log();
+  if (log != NULL) {
+    log->begin_head("%s lock='%d' compile_id='%d' class_id='%s' kind='%s'",
+          tag, is_Lock(), C->compile_id(),
+          is_Unlock() ? "unlock" : is_Lock() ? "lock" : "?",
+          kind_as_string());
+    log->stamp();
+    log->end_head();
+    JVMState* p = is_Unlock() ? (as_Unlock()->dbg_jvms()) : jvms();
+    while (p != NULL) {
+      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+      p = p->caller();
+    }
+    log->tail(tag);
+  }
+}
+
--- a/src/share/vm/opto/callnode.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/callnode.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -985,6 +985,9 @@
   bool is_coarsened()   const { return (_kind == Coarsened); }
   bool is_nested()      const { return (_kind == Nested); }
 
+  const char * kind_as_string() const;
+  void log_lock_optimization(Compile* c, const char * tag) const;
+
   void set_non_esc_obj() { _kind = NonEscObj; set_eliminated_lock_counter(); }
   void set_coarsened()   { _kind = Coarsened; set_eliminated_lock_counter(); }
   void set_nested()      { _kind = Nested; set_eliminated_lock_counter(); }
@@ -1045,15 +1048,24 @@
   }
 
   bool is_nested_lock_region(); // Is this Lock nested?
+  bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested?
 };
 
 //------------------------------Unlock---------------------------------------
 // High-level unlock operation
 class UnlockNode : public AbstractLockNode {
+private:
+#ifdef ASSERT
+  JVMState* const _dbg_jvms;      // Pointer to list of JVM State objects
+#endif
 public:
   virtual int Opcode() const;
   virtual uint size_of() const; // Size is bigger
-  UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) {
+  UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf )
+#ifdef ASSERT
+    , _dbg_jvms(NULL)
+#endif
+  {
     init_class_id(Class_Unlock);
     init_flags(Flag_is_macro);
     C->add_macro_node(this);
@@ -1061,6 +1073,14 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
   // unlock is never a safepoint
   virtual bool        guaranteed_safepoint()  { return false; }
+#ifdef ASSERT
+  void set_dbg_jvms(JVMState* s) {
+    *(JVMState**)&_dbg_jvms = s;  // override const attribute in the accessor
+  }
+  JVMState* dbg_jvms() const { return _dbg_jvms; }
+#else
+  JVMState* dbg_jvms() const { return NULL; }
+#endif
 };
 
 #endif // SHARE_VM_OPTO_CALLNODE_HPP
--- a/src/share/vm/opto/chaitin.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/chaitin.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -575,6 +575,9 @@
   // Peephole remove copies
   post_allocate_copy_removal();
 
+  // Merge multidefs if multiple defs representing the same value are used in a single block.
+  merge_multidefs();
+
 #ifdef ASSERT
   // Veify the graph after RA.
   verify(&live_arena);
@@ -837,7 +840,7 @@
         case Op_RegD:
           lrg.set_num_regs(2);
           // Define platform specific register pressure
-#if defined(SPARC) || defined(ARM)
+#if defined(SPARC) || defined(ARM32)
           lrg.set_reg_pressure(2);
 #elif defined(IA32)
           if( ireg == Op_RegL ) {
--- a/src/share/vm/opto/chaitin.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/chaitin.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -578,6 +578,32 @@
   // Extend the node to LRG mapping
   void add_reference( const Node *node, const Node *old_node);
 
+  // Record the first use of a def in the block for a register.
+  class RegDefUse {
+    Node* _def;
+    Node* _first_use;
+  public:
+    RegDefUse() : _def(NULL), _first_use(NULL) { }
+    Node* def() const       { return _def;       }
+    Node* first_use() const { return _first_use; }
+
+    void update(Node* def, Node* use) {
+      if (_def != def) {
+        _def = def;
+        _first_use = use;
+      }
+    }
+    void clear() {
+      _def = NULL;
+      _first_use = NULL;
+    }
+  };
+  typedef GrowableArray<RegDefUse> RegToDefUseMap;
+  int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse);
+
+  // Merge nodes that are a part of a multidef lrg and produce the same value within a block.
+  void merge_multidefs();
+
 private:
 
   static int _final_loads, _final_stores, _final_copies, _final_memoves;
--- a/src/share/vm/opto/compile.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/compile.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,25 +67,17 @@
 #include "runtime/timer.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/copy.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/escape.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/escape.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -205,6 +205,11 @@
     _verify = false;
   }
 #endif
+  // Bytecode analyzer BCEscapeAnalyzer, used for Call nodes
+  // processing, calls to CI to resolve symbols (types, fields, methods)
+  // referenced in bytecode. During symbol resolution VM may throw
+  // an exception which CI cleans and converts to compilation failure.
+  if (C->failing())  return false;
 
   // 2. Finish Graph construction by propagating references to all
   //    java objects through graph.
@@ -1789,6 +1794,9 @@
             // The lock could be marked eliminated by lock coarsening
             // code during first IGVN before EA. Replace coarsened flag
             // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+            alock->log_lock_optimization(C, "eliminate_lock_set_non_esc3");
+#endif
             alock->set_non_esc_obj();
           }
         }
--- a/src/share/vm/opto/gcm.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/gcm.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,25 +35,17 @@
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "runtime/deoptimization.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/graphKit.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/graphKit.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3211,6 +3211,9 @@
 
   const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type();
   UnlockNode *unlock = new (C) UnlockNode(C, tf);
+#ifdef ASSERT
+  unlock->set_dbg_jvms(sync_jvms());
+#endif
   uint raw_idx = Compile::AliasIdxRaw;
   unlock->init_req( TypeFunc::Control, control() );
   unlock->init_req( TypeFunc::Memory , memory(raw_idx) );
--- a/src/share/vm/opto/lcm.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/lcm.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,25 +30,17 @@
 #include "opto/cfgnode.hpp"
 #include "opto/machnode.hpp"
 #include "opto/runtime.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
@@ -437,8 +429,15 @@
   for (DUIterator_Last i2min, i2 = old_tst->last_outs(i2min); i2 >= i2min; --i2)
     old_tst->last_out(i2)->set_req(0, nul_chk);
   // Clean-up any dead code
-  for (uint i3 = 0; i3 < old_tst->req(); i3++)
+  for (uint i3 = 0; i3 < old_tst->req(); i3++) {
+    Node* in = old_tst->in(i3);
     old_tst->set_req(i3, NULL);
+    if (in->outcnt() == 0) {
+      // Remove dead input node
+      in->disconnect_inputs(NULL, C);
+      block->find_remove(in);
+    }
+  }
 
   latency_from_uses(nul_chk);
   latency_from_uses(best);
--- a/src/share/vm/opto/locknode.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/locknode.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +28,17 @@
 #include "opto/node.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/subnode.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/loopnode.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/loopnode.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -436,6 +436,19 @@
       return false; // cyclic loop or this loop trips only once
   }
 
+  if (phi_incr != NULL) {
+    // check if there is a possiblity of IV overflowing after the first increment
+    if (stride_con > 0) {
+      if (init_t->_hi > max_jint - stride_con) {
+        return false;
+      }
+    } else {
+      if (init_t->_lo < min_jint - stride_con) {
+        return false;
+      }
+    }
+  }
+
   // =================================================
   // ---- SUCCESS!   Found A Trip-Counted Loop!  -----
   //
--- a/src/share/vm/opto/machnode.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/machnode.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -558,6 +558,29 @@
 #endif
 };
 
+// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
+// however it doesn't have a control input and is more like a MergeMem.
+// It is inserted after the register allocation is done to ensure that nodes use single
+// definition of a multidef lrg in a block.
+class MachMergeNode : public MachIdealNode {
+public:
+  MachMergeNode(Node *n1) {
+    init_class_id(Class_MachMerge);
+    add_req(NULL);
+    add_req(n1);
+  }
+  virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
+  virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
+  virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
+  virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
+  virtual uint oper_input_base() const { return 1; }
+  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
+  virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
+#ifndef PRODUCT
+  virtual const char *Name() const { return "MachMerge"; }
+#endif
+};
+
 //------------------------------MachBranchNode--------------------------------
 // Abstract machine branch Node
 class MachBranchNode : public MachIdealNode {
--- a/src/share/vm/opto/macro.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/macro.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1890,7 +1890,7 @@
     // Box is used only in one lock region. Mark this box as eliminated.
     _igvn.hash_delete(oldbox);
     oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value
-    _igvn.hash_insert(oldbox);
+     _igvn.hash_insert(oldbox);
 
     for (uint i = 0; i < oldbox->outcnt(); i++) {
       Node* u = oldbox->raw_out(i);
@@ -1899,6 +1899,9 @@
         // Check lock's box since box could be referenced by Lock's debug info.
         if (alock->box_node() == oldbox) {
           // Mark eliminated all related locks and unlocks.
+#ifdef ASSERT
+          alock->log_lock_optimization(C, "eliminate_lock_set_non_esc4");
+#endif
           alock->set_non_esc_obj();
         }
       }
@@ -1925,6 +1928,9 @@
       AbstractLockNode* alock = u->as_AbstractLock();
       if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) {
         // Replace Box and mark eliminated all related locks and unlocks.
+#ifdef ASSERT
+        alock->log_lock_optimization(C, "eliminate_lock_set_non_esc5");
+#endif
         alock->set_non_esc_obj();
         _igvn.rehash_node_delayed(alock);
         alock->set_box_node(newbox);
@@ -1971,26 +1977,38 @@
        return;
     } else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened
       // Only Lock node has JVMState needed here.
-      if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) {
-        // Mark eliminated related nested locks and unlocks.
-        Node* obj = alock->obj_node();
-        BoxLockNode* box_node = alock->box_node()->as_BoxLock();
-        assert(!box_node->is_eliminated(), "should not be marked yet");
-        // Note: BoxLock node is marked eliminated only here
-        // and it is used to indicate that all associated lock
-        // and unlock nodes are marked for elimination.
-        box_node->set_eliminated(); // Box's hash is always NO_HASH here
-        for (uint i = 0; i < box_node->outcnt(); i++) {
-          Node* u = box_node->raw_out(i);
-          if (u->is_AbstractLock()) {
-            alock = u->as_AbstractLock();
-            if (alock->box_node() == box_node) {
-              // Verify that this Box is referenced only by related locks.
-              assert(alock->obj_node()->eqv_uncast(obj), "");
-              // Mark all related locks and unlocks.
-              alock->set_nested();
+      // Not that preceding claim is documented anywhere else.
+      if (alock->jvms() != NULL) {
+        if (alock->as_Lock()->is_nested_lock_region()) {
+          // Mark eliminated related nested locks and unlocks.
+          Node* obj = alock->obj_node();
+          BoxLockNode* box_node = alock->box_node()->as_BoxLock();
+          assert(!box_node->is_eliminated(), "should not be marked yet");
+          // Note: BoxLock node is marked eliminated only here
+          // and it is used to indicate that all associated lock
+          // and unlock nodes are marked for elimination.
+          box_node->set_eliminated(); // Box's hash is always NO_HASH here
+          for (uint i = 0; i < box_node->outcnt(); i++) {
+            Node* u = box_node->raw_out(i);
+            if (u->is_AbstractLock()) {
+              alock = u->as_AbstractLock();
+              if (alock->box_node() == box_node) {
+                // Verify that this Box is referenced only by related locks.
+                assert(alock->obj_node()->eqv_uncast(obj), "");
+                // Mark all related locks and unlocks.
+#ifdef ASSERT
+                alock->log_lock_optimization(C, "eliminate_lock_set_nested");
+#endif
+                alock->set_nested();
+              }
             }
           }
+        } else {
+#ifdef ASSERT
+          alock->log_lock_optimization(C, "eliminate_lock_NOT_nested_lock_region");
+          if (C->log() != NULL)
+            alock->as_Lock()->is_nested_lock_region(C); // rerun for debugging output
+#endif
         }
       }
       return;
@@ -2035,19 +2053,10 @@
     assert(oldbox->is_eliminated(), "should be done already");
   }
 #endif
-  CompileLog* log = C->log();
-  if (log != NULL) {
-    log->head("eliminate_lock lock='%d'",
-              alock->is_Lock());
-    JVMState* p = alock->jvms();
-    while (p != NULL) {
-      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
-      p = p->caller();
-    }
-    log->tail("eliminate_lock");
-  }
 
-  #ifndef PRODUCT
+  alock->log_lock_optimization(C, "eliminate_lock");
+
+#ifndef PRODUCT
   if (PrintEliminateLocks) {
     if (alock->is_Lock()) {
       tty->print_cr("++++ Eliminated: %d Lock", alock->_idx);
@@ -2055,7 +2064,7 @@
       tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx);
     }
   }
-  #endif
+#endif
 
   Node* mem  = alock->in(TypeFunc::Memory);
   Node* ctrl = alock->in(TypeFunc::Control);
--- a/src/share/vm/opto/matcher.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/matcher.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,25 +38,17 @@
 #include "opto/vectornode.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/node.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/node.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -98,6 +98,7 @@
 class MachSafePointNode;
 class MachSpillCopyNode;
 class MachTempNode;
+class MachMergeNode;
 class Matcher;
 class MemBarNode;
 class MemBarStoreStoreNode;
@@ -591,6 +592,7 @@
       DEFINE_CLASS_ID(MachTemp,         Mach, 3)
       DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
       DEFINE_CLASS_ID(MachConstant,     Mach, 5)
+      DEFINE_CLASS_ID(MachMerge,        Mach, 6)
 
     DEFINE_CLASS_ID(Type,  Node, 2)
       DEFINE_CLASS_ID(Phi,   Type, 0)
@@ -761,6 +763,7 @@
   DEFINE_CLASS_QUERY(MachSafePoint)
   DEFINE_CLASS_QUERY(MachSpillCopy)
   DEFINE_CLASS_QUERY(MachTemp)
+  DEFINE_CLASS_QUERY(MachMerge)
   DEFINE_CLASS_QUERY(Mem)
   DEFINE_CLASS_QUERY(MemBar)
   DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/src/share/vm/opto/output.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/output.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -2473,7 +2473,7 @@
       if( iop == Op_Con ) continue;      // Do not schedule Top
       if( iop == Op_Node &&     // Do not schedule PhiNodes, ProjNodes
           mach->pipeline() == MachNode::pipeline_class() &&
-          !n->is_SpillCopy() )  // Breakpoints, Prolog, etc
+          !n->is_SpillCopy() && !n->is_MachMerge() )  // Breakpoints, Prolog, etc
         continue;
       break;                    // Funny loop structure to be sure...
     }
--- a/src/share/vm/opto/output.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/output.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +27,17 @@
 
 #include "opto/block.hpp"
 #include "opto/node.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/phase.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/phase.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -74,6 +74,7 @@
 elapsedTimer   Phase::_t_computeLive;
 elapsedTimer   Phase::_t_regAllocSplit;
 elapsedTimer   Phase::_t_postAllocCopyRemoval;
+elapsedTimer   Phase::_t_mergeMultidefs;
 elapsedTimer   Phase::_t_fixupSpills;
 
 // Subtimers for _t_output
@@ -136,11 +137,12 @@
     tty->print_cr ("      computeLive    : %3.3f sec", Phase::_t_computeLive.seconds());
     tty->print_cr ("      regAllocSplit  : %3.3f sec", Phase::_t_regAllocSplit.seconds());
     tty->print_cr ("      postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds());
+    tty->print_cr ("      mergeMultidefs: %3.3f sec", Phase::_t_mergeMultidefs.seconds());
     tty->print_cr ("      fixupSpills    : %3.3f sec", Phase::_t_fixupSpills.seconds());
     double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() +
       Phase::_t_buildIFGphysical.seconds() + Phase::_t_computeLive.seconds() +
       Phase::_t_regAllocSplit.seconds()    + Phase::_t_fixupSpills.seconds() +
-      Phase::_t_postAllocCopyRemoval.seconds();
+      Phase::_t_postAllocCopyRemoval.seconds() + Phase::_t_mergeMultidefs.seconds();
     double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0));
     tty->print_cr ("      subtotal       : %3.3f sec,  %3.2f %%", regalloc_subtotal, percent_of_regalloc);
   }
--- a/src/share/vm/opto/phase.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/phase.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -109,6 +109,7 @@
   static elapsedTimer   _t_computeLive;
   static elapsedTimer   _t_regAllocSplit;
   static elapsedTimer   _t_postAllocCopyRemoval;
+  static elapsedTimer   _t_mergeMultidefs;
   static elapsedTimer   _t_fixupSpills;
 
 // Subtimers for _t_output
--- a/src/share/vm/opto/postaloc.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/postaloc.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -263,20 +263,6 @@
   // intermediate copies might be illegal, i.e., value is stored down to stack
   // then reloaded BUT survives in a register the whole way.
   Node *val = skip_copies(n->in(k));
-
-  if (val == x && nk_idx != 0 &&
-      regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
-      _lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
-    // When rematerialzing nodes and stretching lifetimes, the
-    // allocator will reuse the original def for multidef LRG instead
-    // of the current reaching def because it can't know it's safe to
-    // do so.  After allocation completes if they are in the same LRG
-    // then it should use the current reaching def instead.
-    n->set_req(k, regnd[nk_reg]);
-    blk_adjust += yank_if_dead(val, current_block, &value, &regnd);
-    val = skip_copies(n->in(k));
-  }
-
   if (val == x) return blk_adjust; // No progress?
 
   int n_regs = RegMask::num_registers(val->ideal_reg());
@@ -382,6 +368,95 @@
   return false;
 }
 
+// The algorithms works as follows:
+// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k
+// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've
+// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their
+// current reaching definitions (we track only multidefs though). With each definition we also associate the first
+// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the
+// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute
+// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg
+// as they get encountered with the merge node and keep adding these defs to the merge inputs.
+void PhaseChaitin::merge_multidefs() {
+  NOT_PRODUCT( Compile::TracePhase t3("mergeMultidefs", &_t_mergeMultidefs, TimeCompiler); )
+  ResourceMark rm;
+  // Keep track of the defs seen in registers and collect their uses in the block.
+  RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
+  for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
+    Block* block = _cfg.get_block(i);
+    for (uint j = 1; j < block->number_of_nodes(); j++) {
+      Node* n = block->get_node(j);
+      if (n->is_Phi()) continue;
+      for (uint k = 1; k < n->req(); k++) {
+        j += possibly_merge_multidef(n, k, block, reg2defuse);
+      }
+      // Null out the value produced by the instruction itself, since we're only interested in defs
+      // implicitly defined by the uses. We are actually interested in tracking only redefinitions
+      // of the multidef lrgs in the same register. For that matter it's enough to track changes in
+      // the base register only and ignore other effects of multi-register lrgs and fat projections.
+      // It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of
+      // those our register is guaranteed to be used by another lrg and we won't attempt to merge it.
+      uint lrg = _lrg_map.live_range_id(n);
+      if (lrg > 0 && lrgs(lrg).is_multidef()) {
+        OptoReg::Name reg = lrgs(lrg).reg();
+        reg2defuse.at(reg).clear();
+      }
+    }
+    // Clear reg->def->use tracking for the next block
+    for (int j = 0; j < reg2defuse.length(); j++) {
+      reg2defuse.at(j).clear();
+    }
+  }
+}
+
+int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
+  int blk_adjust = 0;
+
+  uint lrg = _lrg_map.live_range_id(n->in(k));
+  if (lrg > 0 && lrgs(lrg).is_multidef()) {
+    OptoReg::Name reg = lrgs(lrg).reg();
+
+    Node* def = reg2defuse.at(reg).def();
+    if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
+      // Same lrg but different node, we have to merge.
+      MachMergeNode* merge;
+      if (def->is_MachMerge()) { // is it already a merge?
+        merge = def->as_MachMerge();
+      } else {
+        merge = new (C) MachMergeNode(def);
+
+        // Insert the merge node into the block before the first use.
+        uint use_index = block->find_node(reg2defuse.at(reg).first_use());
+        block->insert_node(merge, use_index++);
+        _cfg.map_node_to_block(merge, block);
+
+        // Let the allocator know about the new node, use the same lrg
+        _lrg_map.extend(merge->_idx, lrg);
+        blk_adjust++;
+
+        // Fixup all the uses (there is at least one) that happened between the first
+        // use and before the current one.
+        for (; use_index < block->number_of_nodes(); use_index++) {
+          Node* use = block->get_node(use_index);
+          if (use == n) {
+            break;
+          }
+          use->replace_edge(def, merge);
+        }
+      }
+      if (merge->find_edge(n->in(k)) == -1) {
+        merge->add_req(n->in(k));
+      }
+      n->set_req(k, merge);
+    }
+
+    // update the uses
+    reg2defuse.at(reg).update(n->in(k), n);
+  }
+
+  return blk_adjust;
+}
+
 
 //------------------------------post_allocate_copy_removal---------------------
 // Post-Allocation peephole copy removal.  We do this in 1 pass over the
--- a/src/share/vm/opto/regmask.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/regmask.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +25,17 @@
 #include "precompiled.hpp"
 #include "opto/compile.hpp"
 #include "opto/regmask.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/regmask.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/regmask.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +28,17 @@
 #include "code/vmreg.hpp"
 #include "libadt/port.hpp"
 #include "opto/optoreg.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined ADGLOBALS_MD_HPP
+# include ADGLOBALS_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/adGlobals_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/adGlobals_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/adGlobals_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/adGlobals_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/adGlobals_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/adGlobals_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/adGlobals_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/runtime.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/runtime.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +68,17 @@
 #include "runtime/vframe_hp.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/preserveException.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 
--- a/src/share/vm/opto/stringopts.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/stringopts.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1507,10 +1507,12 @@
       }
       case StringConcat::StringMode: {
         const Type* type = kit.gvn().type(arg);
+        Node* count = NULL;
         if (type == TypePtr::NULL_PTR) {
           // replace the argument with the null checked version
           arg = null_string;
           sc->set_argument(argi, arg);
+          count = kit.load_String_length(kit.control(), arg);
         } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
           // s = s != null ? s : "null";
           // length = length + (s.count - s.offset);
@@ -1533,10 +1535,13 @@
           // replace the argument with the null checked version
           arg = phi;
           sc->set_argument(argi, arg);
+          count = kit.load_String_length(kit.control(), arg);
+        } else {
+          // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
+          // kit.control might be a different test, that can be hoisted above the actual nullcheck
+          // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
+          count = kit.load_String_length(NULL, arg);
         }
-
-        Node* count = kit.load_String_length(kit.control(), arg);
-
         length = __ AddI(length, count);
         string_sizes->init_req(argi, NULL);
         break;
--- a/src/share/vm/opto/type.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/opto/type.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -3950,7 +3950,9 @@
            (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) ||
            // 'this' is exact and super or unrelated:
            (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
-      tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
+      if (above_centerline(ptr)) {
+        tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
+      }
       return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot);
     }
 
--- a/src/share/vm/prims/jniCheck.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/jniCheck.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,8 @@
 # include "jniTypes_ppc.hpp"
 #endif
 
+// Complain every extra number of unplanned local refs
+#define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32
 
 // Heap objects are allowed to be directly referenced only in VM code,
 // not in native code.
@@ -168,12 +170,42 @@
  * SUPPORT FUNCTIONS
  */
 
+/**
+ * Check whether or not a programmer has actually checked for exceptions. According
+ * to the JNI Specification ("jni/spec/design.html#java_exceptions"):
+ *
+ * There are two cases where the programmer needs to check for exceptions without
+ * being able to first check an error code:
+ *
+ * - The JNI functions that invoke a Java method return the result of the Java method.
+ * The programmer must call ExceptionOccurred() to check for possible exceptions
+ * that occurred during the execution of the Java method.
+ *
+ * - Some of the JNI array access functions do not return an error code, but may
+ * throw an ArrayIndexOutOfBoundsException or ArrayStoreException.
+ *
+ * In all other cases, a non-error return value guarantees that no exceptions have been thrown.
+ */
+static inline void
+check_pending_exception(JavaThread* thr) {
+  if (thr->has_pending_exception()) {
+    NativeReportJNIWarning(thr, "JNI call made with exception pending");
+  }
+  if (thr->is_pending_jni_exception_check()) {
+    IN_VM(
+      tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s",
+        thr->get_pending_jni_exception_check());
+      thr->print_stack();
+    )
+    thr->clear_pending_jni_exception_check(); // Just complain once
+  }
+}
+
+
 static inline void
 functionEnterCritical(JavaThread* thr)
 {
-  if (thr->has_pending_exception()) {
-    NativeReportJNIWarning(thr, "JNI call made with exception pending");
-  }
+  check_pending_exception(thr);
 }
 
 static inline void
@@ -187,9 +219,7 @@
   if (thr->in_critical()) {
     tty->print_cr("%s", warn_other_function_in_critical);
   }
-  if (thr->has_pending_exception()) {
-    NativeReportJNIWarning(thr, "JNI call made with exception pending");
-  }
+  check_pending_exception(thr);
 }
 
 static inline void
@@ -201,9 +231,20 @@
 }
 
 static inline void
-functionExit(JNIEnv *env)
+functionExit(JavaThread* thr)
 {
-  /* nothing to do at this time */
+  JNIHandleBlock* handles = thr->active_handles();
+  size_t planned_capacity = handles->get_planned_capacity();
+  size_t live_handles = handles->get_number_of_live_handles();
+  if (live_handles > planned_capacity) {
+    IN_VM(
+      tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu",
+          live_handles, planned_capacity);
+      thr->print_stack();
+    )
+    // Complain just the once, reset to current + warn threshold
+    handles->set_planned_capacity(live_handles + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD);
+  }
 }
 
 static inline void
@@ -508,7 +549,7 @@
       jniCheck::validate_object(thr, loader);
     )
     jclass result = UNCHECKED()->DefineClass(env, name, loader, buf, len);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -520,7 +561,7 @@
       jniCheck::validate_class_descriptor(thr, name);
     )
     jclass result = UNCHECKED()->FindClass(env, name);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -532,7 +573,7 @@
       jniCheck::validate_object(thr, method);
     )
     jmethodID result = UNCHECKED()->FromReflectedMethod(env, method);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -544,7 +585,7 @@
       jniCheck::validate_object(thr, field);
     )
     jfieldID result = UNCHECKED()->FromReflectedField(env, field);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -560,7 +601,7 @@
     )
     jobject result = UNCHECKED()->ToReflectedMethod(env, cls, methodID,
                                                     isStatic);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -572,7 +613,7 @@
       jniCheck::validate_class(thr, sub, true);
     )
     jclass result = UNCHECKED()->GetSuperclass(env, sub);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -586,7 +627,7 @@
       jniCheck::validate_class(thr, sup, true);
     )
     jboolean result = UNCHECKED()->IsAssignableFrom(env, sub, sup);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -601,7 +642,7 @@
     )
     jobject result = UNCHECKED()->ToReflectedField(env, cls, fieldID,
                                                    isStatic);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -619,7 +660,7 @@
       }
     )
     jint result = UNCHECKED()->Throw(env, obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -634,15 +675,16 @@
       jniCheck::validate_throwable_klass(thr, k);
     )
     jint result = UNCHECKED()->ThrowNew(env, clazz, msg);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
 JNI_ENTRY_CHECKED(jthrowable,
   checked_jni_ExceptionOccurred(JNIEnv *env))
+    thr->clear_pending_jni_exception_check();
     functionEnterExceptionAllowed(thr);
     jthrowable result = UNCHECKED()->ExceptionOccurred(env);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -650,22 +692,24 @@
   checked_jni_ExceptionDescribe(JNIEnv *env))
     functionEnterExceptionAllowed(thr);
     UNCHECKED()->ExceptionDescribe(env);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
   checked_jni_ExceptionClear(JNIEnv *env))
+    thr->clear_pending_jni_exception_check();
     functionEnterExceptionAllowed(thr);
     UNCHECKED()->ExceptionClear(env);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
   checked_jni_FatalError(JNIEnv *env,
                          const char *msg))
+    thr->clear_pending_jni_exception_check();
     functionEnter(thr);
     UNCHECKED()->FatalError(env, msg);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jint,
@@ -675,7 +719,10 @@
     if (capacity < 0)
       NativeReportJNIFatalError(thr, "negative capacity");
     jint result = UNCHECKED()->PushLocalFrame(env, capacity);
-    functionExit(env);
+    if (result == JNI_OK) {
+      thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD);
+    }
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -684,7 +731,7 @@
                             jobject result))
     functionEnterExceptionAllowed(thr);
     jobject res = UNCHECKED()->PopLocalFrame(env, result);
-    functionExit(env);
+    functionExit(thr);
     return res;
 JNI_END
 
@@ -698,7 +745,7 @@
       }
     )
     jobject result = UNCHECKED()->NewGlobalRef(env,lobj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -714,7 +761,7 @@
       }
     )
     UNCHECKED()->DeleteGlobalRef(env,gref);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -729,7 +776,7 @@
             "Invalid local JNI handle passed to DeleteLocalRef");
     )
     UNCHECKED()->DeleteLocalRef(env, obj);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jboolean,
@@ -750,7 +797,7 @@
       }
     )
     jboolean result = UNCHECKED()->IsSameObject(env,obj1,obj2);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -764,7 +811,7 @@
       }
     )
     jobject result = UNCHECKED()->NewLocalRef(env, ref);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -776,7 +823,10 @@
       NativeReportJNIFatalError(thr, "negative capacity");
     }
     jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity);
-    functionExit(env);
+    if (result == JNI_OK) {
+      thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD);
+    }
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -788,7 +838,7 @@
       jniCheck::validate_class(thr, clazz, false);
     )
     jobject result = UNCHECKED()->AllocObject(env,clazz);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -806,7 +856,7 @@
     va_start(args, methodID);
     jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args);
     va_end(args);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -821,7 +871,7 @@
       jniCheck::validate_jmethod_id(thr, methodID);
     )
     jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -836,7 +886,7 @@
       jniCheck::validate_jmethod_id(thr, methodID);
     )
     jobject result = UNCHECKED()->NewObjectA(env,clazz,methodID,args);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -848,7 +898,7 @@
       jniCheck::validate_object(thr, obj);
     )
     jclass result = UNCHECKED()->GetObjectClass(env,obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -862,7 +912,7 @@
       jniCheck::validate_class(thr, clazz, true);
     )
     jboolean result = UNCHECKED()->IsInstanceOf(env,obj,clazz);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -876,7 +926,7 @@
       jniCheck::validate_class(thr, clazz, false);
     )
     jmethodID result = UNCHECKED()->GetMethodID(env,clazz,name,sig);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -895,7 +945,8 @@
     ResultType result =UNCHECKED()->Call##Result##MethodV(env, obj, methodID, \
                                                           args); \
     va_end(args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("Call"#Result"Method"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -910,7 +961,8 @@
     ) \
     ResultType result = UNCHECKED()->Call##Result##MethodV(env, obj, methodID,\
                                                            args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("Call"#Result"MethodV"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -925,7 +977,8 @@
     ) \
     ResultType result = UNCHECKED()->Call##Result##MethodA(env, obj, methodID,\
                                                            args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("Call"#Result"MethodA"); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -952,7 +1005,8 @@
     va_start(args,methodID);
     UNCHECKED()->CallVoidMethodV(env,obj,methodID,args);
     va_end(args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallVoidMethod");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -965,7 +1019,8 @@
       jniCheck::validate_call_object(thr, obj, methodID);
     )
     UNCHECKED()->CallVoidMethodV(env,obj,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallVoidMethodV");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -978,7 +1033,8 @@
       jniCheck::validate_call_object(thr, obj, methodID);
     )
     UNCHECKED()->CallVoidMethodA(env,obj,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallVoidMethodA");
+    functionExit(thr);
 JNI_END
 
 #define WRAPPER_CallNonvirtualMethod(ResultType, Result) \
@@ -1001,7 +1057,8 @@
                                                                      methodID,\
                                                                      args); \
     va_end(args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallNonvirtual"#Result"Method"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -1021,7 +1078,8 @@
                                                                      clazz, \
                                                                      methodID,\
                                                                      args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodV"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -1041,7 +1099,8 @@
                                                                      clazz, \
                                                                      methodID,\
                                                                      args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodA"); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -1070,7 +1129,8 @@
     va_start(args,methodID);
     UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args);
     va_end(args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallNonvirtualVoidMethod");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1085,7 +1145,8 @@
       jniCheck::validate_call_class(thr, clazz, methodID);
     )
     UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodV");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1100,7 +1161,8 @@
       jniCheck::validate_call_class(thr, clazz, methodID);
     )
     UNCHECKED()->CallNonvirtualVoidMethodA(env,obj,clazz,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodA");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jfieldID,
@@ -1113,7 +1175,7 @@
       jniCheck::validate_class(thr, clazz, false);
     )
     jfieldID result = UNCHECKED()->GetFieldID(env,clazz,name,sig);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1127,7 +1189,7 @@
       checkInstanceFieldID(thr, fieldID, obj, FieldType); \
     ) \
     ReturnType result = UNCHECKED()->Get##Result##Field(env,obj,fieldID); \
-    functionExit(env); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -1152,7 +1214,7 @@
       checkInstanceFieldID(thr, fieldID, obj, FieldType); \
     ) \
     UNCHECKED()->Set##Result##Field(env,obj,fieldID,val); \
-    functionExit(env); \
+    functionExit(thr); \
 JNI_END
 
 WRAPPER_SetField(jobject,  Object,  T_OBJECT)
@@ -1176,7 +1238,7 @@
       jniCheck::validate_class(thr, clazz, false);
     )
     jmethodID result = UNCHECKED()->GetStaticMethodID(env,clazz,name,sig);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1198,7 +1260,8 @@
                                                                  methodID, \
                                                                  args); \
     va_end(args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallStatic"#Result"Method"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -1216,7 +1279,8 @@
                                                                  clazz, \
                                                                  methodID, \
                                                                  args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallStatic"#Result"MethodV"); \
+    functionExit(thr); \
     return result; \
 JNI_END \
 \
@@ -1234,7 +1298,8 @@
                                                                  clazz, \
                                                                  methodID, \
                                                                  args); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("CallStatic"#Result"MethodA"); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -1262,7 +1327,8 @@
     va_start(args,methodID);
     UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args);
     va_end(args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallStaticVoidMethod");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1276,7 +1342,8 @@
       jniCheck::validate_class(thr, cls, false);
     )
     UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallStaticVoidMethodV");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1290,7 +1357,8 @@
       jniCheck::validate_class(thr, cls, false);
     )
     UNCHECKED()->CallStaticVoidMethodA(env,cls,methodID,args);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("CallStaticVoidMethodA");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jfieldID,
@@ -1303,7 +1371,7 @@
       jniCheck::validate_class(thr, clazz, false);
     )
     jfieldID result = UNCHECKED()->GetStaticFieldID(env,clazz,name,sig);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1320,7 +1388,7 @@
     ReturnType result = UNCHECKED()->GetStatic##Result##Field(env, \
                                                               clazz, \
                                                               fieldID); \
-    functionExit(env); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -1346,7 +1414,7 @@
       checkStaticFieldID(thr, fieldID, clazz, FieldType); \
     ) \
     UNCHECKED()->SetStatic##Result##Field(env,clazz,fieldID,value); \
-    functionExit(env); \
+    functionExit(thr); \
 JNI_END
 
 WRAPPER_SetStaticField(jobject,  Object,  T_OBJECT)
@@ -1366,7 +1434,7 @@
                         jsize len))
     functionEnter(thr);
     jstring result = UNCHECKED()->NewString(env,unicode,len);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1378,7 +1446,7 @@
       checkString(thr, str);
     )
     jsize result = UNCHECKED()->GetStringLength(env,str);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1407,7 +1475,7 @@
       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
       FreeHeap((char*)result);
     }
-    functionExit(env);
+    functionExit(thr);
     return new_result;
 JNI_END
 
@@ -1442,7 +1510,7 @@
        UNCHECKED()->ReleaseStringChars(env, str,
            (const jchar*) guarded.release_for_freeing());
     }
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jstring,
@@ -1450,7 +1518,7 @@
                            const char *utf))
     functionEnter(thr);
     jstring result = UNCHECKED()->NewStringUTF(env,utf);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1462,7 +1530,7 @@
       checkString(thr, str);
     )
     jsize result = UNCHECKED()->GetStringUTFLength(env,str);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1490,7 +1558,7 @@
       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
       FreeHeap((char*)result, mtInternal);
     }
-    functionExit(env);
+    functionExit(thr);
     return new_result;
 JNI_END
 
@@ -1525,7 +1593,7 @@
       UNCHECKED()->ReleaseStringUTFChars(env, str,
           (const char*) guarded.release_for_freeing());
     }
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jsize,
@@ -1536,7 +1604,7 @@
       check_is_array(thr, array);
     )
     jsize result = UNCHECKED()->GetArrayLength(env,array);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1547,7 +1615,7 @@
                              jobject init))
     functionEnter(thr);
     jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1560,7 +1628,8 @@
       check_is_obj_array(thr, array);
     )
     jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("GetObjectArrayElement");
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1574,7 +1643,8 @@
       check_is_obj_array(thr, array);
     )
     UNCHECKED()->SetObjectArrayElement(env,array,index,val);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("SetObjectArrayElement");
+    functionExit(thr);
 JNI_END
 
 #define WRAPPER_NewScalarArray(Return, Result) \
@@ -1583,7 +1653,7 @@
                                  jsize len)) \
     functionEnter(thr); \
     Return result = UNCHECKED()->New##Result##Array(env,len); \
-    functionExit(env); \
+    functionExit(thr); \
     return (Return) result; \
 JNI_END
 
@@ -1611,7 +1681,7 @@
     if (result != NULL) { \
       result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
     } \
-    functionExit(env); \
+    functionExit(thr); \
     return result; \
 JNI_END
 
@@ -1639,7 +1709,7 @@
     ElementType* orig_result = (ElementType *) check_wrapped_array_release( \
         thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \
     UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \
-    functionExit(env); \
+    functionExit(thr); \
 JNI_END
 
 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
@@ -1663,7 +1733,8 @@
       check_primitive_array_type(thr, array, ElementTag); \
     ) \
     UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("Get"#Result"ArrayRegion"); \
+    functionExit(thr); \
 JNI_END
 
 WRAPPER_GetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean)
@@ -1687,7 +1758,8 @@
       check_primitive_array_type(thr, array, ElementTag); \
     ) \
     UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \
-    functionExit(env); \
+    thr->set_pending_jni_exception_check("Set"#Result"ArrayRegion"); \
+    functionExit(thr); \
 JNI_END
 
 WRAPPER_SetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean)
@@ -1706,7 +1778,7 @@
                               jint nMethods))
     functionEnter(thr);
     jint result = UNCHECKED()->RegisterNatives(env,clazz,methods,nMethods);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1715,7 +1787,7 @@
                                 jclass clazz))
     functionEnter(thr);
     jint result = UNCHECKED()->UnregisterNatives(env,clazz);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1727,7 +1799,7 @@
       jniCheck::validate_object(thr, obj);
     )
     jint result = UNCHECKED()->MonitorEnter(env,obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1739,7 +1811,7 @@
       jniCheck::validate_object(thr, obj);
     )
     jint result = UNCHECKED()->MonitorExit(env,obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1748,7 +1820,7 @@
                         JavaVM **vm))
     functionEnter(thr);
     jint result = UNCHECKED()->GetJavaVM(env,vm);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1763,7 +1835,8 @@
       checkString(thr, str);
     )
     UNCHECKED()->GetStringRegion(env, str, start, len, buf);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("GetStringRegion");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1777,7 +1850,8 @@
       checkString(thr, str);
     )
     UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf);
-    functionExit(env);
+    thr->set_pending_jni_exception_check("GetStringUTFRegion");
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(void *,
@@ -1792,7 +1866,7 @@
     if (result != NULL) {
       result = check_jni_wrap_copy_array(thr, array, result);
     }
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1808,7 +1882,7 @@
     // Check the element array...
     void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode);
     UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(const jchar*,
@@ -1820,7 +1894,7 @@
       checkString(thr, string);
     )
     const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1836,7 +1910,7 @@
      * string parameter as a minor sanity check
      */
     UNCHECKED()->ReleaseStringCritical(env, str, chars);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jweak,
@@ -1849,7 +1923,7 @@
       }
     )
     jweak result = UNCHECKED()->NewWeakGlobalRef(env, obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1858,14 +1932,15 @@
                                   jweak ref))
     functionEnterExceptionAllowed(thr);
     UNCHECKED()->DeleteWeakGlobalRef(env, ref);
-    functionExit(env);
+    functionExit(thr);
 JNI_END
 
 JNI_ENTRY_CHECKED(jboolean,
   checked_jni_ExceptionCheck(JNIEnv *env))
+    thr->clear_pending_jni_exception_check();
     functionEnterExceptionAllowed(thr);
     jboolean result = UNCHECKED()->ExceptionCheck(env);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1875,7 +1950,7 @@
                                   jlong capacity))
     functionEnter(thr);
     jobject result = UNCHECKED()->NewDirectByteBuffer(env, address, capacity);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1884,7 +1959,7 @@
                                      jobject buf))
     functionEnter(thr);
     void* result = UNCHECKED()->GetDirectBufferAddress(env, buf);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1893,7 +1968,7 @@
                                       jobject buf))
     functionEnter(thr);
     jlong result = UNCHECKED()->GetDirectBufferCapacity(env, buf);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1906,7 +1981,7 @@
       jniCheck::validate_object(thr, obj);
     )
     jobjectRefType result = UNCHECKED()->GetObjectRefType(env, obj);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
@@ -1915,7 +1990,7 @@
   checked_jni_GetVersion(JNIEnv *env))
     functionEnter(thr);
     jint result = UNCHECKED()->GetVersion(env);
-    functionExit(env);
+    functionExit(thr);
     return result;
 JNI_END
 
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -68,11 +68,11 @@
 
   ~JvmtiConstantPoolReconstituter() {
     if (_symmap != NULL) {
-      os::free(_symmap, mtClass);
+      delete _symmap;
       _symmap = NULL;
     }
     if (_classmap != NULL) {
-      os::free(_classmap, mtClass);
+      delete _classmap;
       _classmap = NULL;
     }
   }
--- a/src/share/vm/prims/jvmtiImpl.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "interpreter/interpreter.hpp"
+#include "interpreter/oopMapCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
@@ -744,6 +745,13 @@
 }
 
 void VM_GetOrSetLocal::doit() {
+  InterpreterOopMap oop_mask;
+  _jvf->method()->mask_for(_jvf->bci(), &oop_mask);
+  if (oop_mask.is_dead(_index)) {
+    // The local can be invalid and uninitialized in the scope of current bci
+    _result = JVMTI_ERROR_INVALID_SLOT;
+    return;
+  }
   if (_set) {
     // Force deoptimization of frame if compiled because it's
     // possible the compiler emitted some locals as constant values,
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -777,9 +777,13 @@
           Method* idnum_owner = scratch_class->method_with_idnum(old_num);
           if (idnum_owner != NULL) {
             // There is already a method assigned this idnum -- switch them
+            // Take current and original idnum from the new_method
             idnum_owner->set_method_idnum(new_num);
+            idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum());
           }
+          // Take current and original idnum from the old_method
           k_new_method->set_method_idnum(old_num);
+          k_new_method->set_orig_method_idnum(k_old_method->orig_method_idnum());
           if (thread->has_pending_exception()) {
             return JVMTI_ERROR_OUT_OF_MEMORY;
           }
@@ -812,9 +816,12 @@
         Method* idnum_owner = scratch_class->method_with_idnum(num);
         if (idnum_owner != NULL) {
           // There is already a method assigned this idnum -- switch them
+          // Take current and original idnum from the new_method
           idnum_owner->set_method_idnum(new_num);
+          idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum());
         }
         k_new_method->set_method_idnum(num);
+        k_new_method->set_orig_method_idnum(num);
         if (thread->has_pending_exception()) {
           return JVMTI_ERROR_OUT_OF_MEMORY;
         }
@@ -3322,6 +3329,7 @@
   // This is a very busy routine. We don't want too much tracing
   // printed out.
   bool trace_name_printed = false;
+  InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop);
 
   // Very noisy: only enable this call if you are trying to determine
   // that a specific class gets found by this routine.
@@ -3333,10 +3341,8 @@
   // If the class being redefined is java.lang.Object, we need to fix all
   // array class vtables also
   if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) {
-    k->vtable()->adjust_method_entries(_matching_old_methods,
-                                       _matching_new_methods,
-                                       _matching_methods_length,
-                                       &trace_name_printed);
+    k->vtable()->adjust_method_entries(the_class, &trace_name_printed);
+
   } else if (k->oop_is_instance()) {
     HandleMark hm(_thread);
     InstanceKlass *ik = InstanceKlass::cast(k);
@@ -3376,14 +3382,9 @@
         || ik->is_subtype_of(_the_class_oop))) {
       // ik->vtable() creates a wrapper object; rm cleans it up
       ResourceMark rm(_thread);
-      ik->vtable()->adjust_method_entries(_matching_old_methods,
-                                          _matching_new_methods,
-                                          _matching_methods_length,
-                                          &trace_name_printed);
-      ik->adjust_default_methods(_matching_old_methods,
-                                 _matching_new_methods,
-                                 _matching_methods_length,
-                                 &trace_name_printed);
+
+      ik->vtable()->adjust_method_entries(the_class, &trace_name_printed);
+      ik->adjust_default_methods(the_class, &trace_name_printed);
     }
 
     // If the current class has an itable and we are either redefining an
@@ -3396,10 +3397,8 @@
         || ik->is_subclass_of(_the_class_oop))) {
       // ik->itable() creates a wrapper object; rm cleans it up
       ResourceMark rm(_thread);
-      ik->itable()->adjust_method_entries(_matching_old_methods,
-                                          _matching_new_methods,
-                                          _matching_methods_length,
-                                          &trace_name_printed);
+
+      ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
     }
 
     // The constant pools in other classes (other_cp) can refer to
@@ -3423,10 +3422,7 @@
       other_cp = constantPoolHandle(ik->constants());
       cp_cache = other_cp->cache();
       if (cp_cache != NULL) {
-        cp_cache->adjust_method_entries(_matching_old_methods,
-                                        _matching_new_methods,
-                                        _matching_methods_length,
-                                        &trace_name_printed);
+        cp_cache->adjust_method_entries(the_class, &trace_name_printed);
       }
     }
 
@@ -3555,6 +3551,7 @@
 
       // obsolete methods need a unique idnum so they become new entries in
       // the jmethodID cache in InstanceKlass
+      assert(old_method->method_idnum() == new_method->method_idnum(), "must match");
       u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum();
       if (num != ConstMethod::UNSET_IDNUM) {
         old_method->set_method_idnum(num);
@@ -3575,7 +3572,8 @@
     assert(!old_method->has_vtable_index(),
            "cannot delete methods with vtable entries");;
 
-    // Mark all deleted methods as old and obsolete
+    // Mark all deleted methods as old, obsolete and deleted
+    old_method->set_is_deleted();
     old_method->set_is_old();
     old_method->set_is_obsolete();
     ++obsolete_count;
@@ -3981,14 +3979,13 @@
     // the_class doesn't have a cache yet so copy it
     the_class->set_cached_class_file(scratch_class->get_cached_class_file());
   }
-#ifndef PRODUCT
-  else {
-    assert(the_class->get_cached_class_file_bytes() ==
-      scratch_class->get_cached_class_file_bytes(), "cache ptrs must match");
-    assert(the_class->get_cached_class_file_len() ==
-      scratch_class->get_cached_class_file_len(), "cache lens must match");
+  else if (scratch_class->get_cached_class_file_bytes() !=
+           the_class->get_cached_class_file_bytes()) {
+    // The same class can be present twice in the scratch classes list or there
+    // are multiple concurrent RetransformClasses calls on different threads.
+    // In such cases we have to deallocate scratch_class cached_class_file_bytes.
+    os::free(scratch_class->get_cached_class_file_bytes());
   }
-#endif
 
   // NULL out in scratch class to not delete twice.  The class to be redefined
   // always owns these bytes.
@@ -4164,7 +4161,7 @@
       no_old_methods = false;
     }
 
-    // the constant pool cache should never contain old or obsolete methods
+    // the constant pool cache should never contain non-deleted old or obsolete methods
     if (ik->constants() != NULL &&
         ik->constants()->cache() != NULL &&
         !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1045,10 +1045,16 @@
 {
   assert(str->klass() == SystemDictionary::String_klass(), "not a string");
 
+  typeArrayOop s_value = java_lang_String::value(str);
+
+  // JDK-6584008: the value field may be null if a String instance is
+  // partially constructed.
+  if (s_value == NULL) {
+    return 0;
+  }
   // get the string value and length
   // (string value may be offset from the base)
   int s_len = java_lang_String::length(str);
-  typeArrayOop s_value = java_lang_String::value(str);
   int s_offset = java_lang_String::offset(str);
   jchar* value;
   if (s_len > 0) {
--- a/src/share/vm/prims/unsafe.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/prims/unsafe.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -322,10 +322,33 @@
 UNSAFE_END
 
 #ifndef SUPPORTS_NATIVE_CX8
-// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions
 
-// Volatile long versions must use locks if !VM_Version::supports_cx8().
-// support_cx8 is a surrogate for 'supports atomic long memory ops'.
+// VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'.
+//
+// On platforms which do not support atomic compare-and-swap of jlong (8 byte)
+// values we have to use a lock-based scheme to enforce atomicity. This has to be
+// applied to all Unsafe operations that set the value of a jlong field. Even so
+// the compareAndSwapLong operation will not be atomic with respect to direct stores
+// to the field from Java code. It is important therefore that any Java code that
+// utilizes these Unsafe jlong operations does not perform direct stores. To permit
+// direct loads of the field from Java code we must also use Atomic::store within the
+// locked regions. And for good measure, in case there are direct stores, we also
+// employ Atomic::load within those regions. Note that the field in question must be
+// volatile and so must have atomic load/store accesses applied at the Java level.
+//
+// The locking scheme could utilize a range of strategies for controlling the locking
+// granularity: from a lock per-field through to a single global lock. The latter is
+// the simplest and is used for the current implementation. Note that the Java object
+// that contains the field, can not, in general, be used for locking. To do so can lead
+// to deadlocks as we may introduce locking into what appears to the Java code to be a
+// lock-free path.
+//
+// As all the locked-regions are very short and themselves non-blocking we can treat
+// them as leaf routines and elide safepoint checks (ie we don't perform any thread
+// state transitions even when blocking for the lock). Note that if we do choose to
+// add safepoint checks and thread state transitions, we must ensure that we calculate
+// the address of the field _after_ we have acquired the lock, else the object may have
+// been moved by the GC
 
 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
   UnsafeWrapper("Unsafe_GetLongVolatile");
@@ -337,8 +360,8 @@
     else {
       Handle p (THREAD, JNIHandles::resolve(obj));
       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
-      ObjectLocker ol(p, THREAD);
-      jlong value = *addr;
+      MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+      jlong value = Atomic::load(addr);
       return value;
     }
   }
@@ -353,8 +376,8 @@
     else {
       Handle p (THREAD, JNIHandles::resolve(obj));
       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
-      ObjectLocker ol(p, THREAD);
-      *addr = x;
+      MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+      Atomic::store(x, addr);
     }
   }
 UNSAFE_END
@@ -463,8 +486,8 @@
     else {
       Handle p (THREAD, JNIHandles::resolve(obj));
       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
-      ObjectLocker ol(p, THREAD);
-      *addr = x;
+      MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+      Atomic::store(x, addr);
     }
   }
 #endif
@@ -1213,14 +1236,19 @@
   UnsafeWrapper("Unsafe_CompareAndSwapLong");
   Handle p (THREAD, JNIHandles::resolve(obj));
   jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+#ifdef SUPPORTS_NATIVE_CX8
+  return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
+#else
   if (VM_Version::supports_cx8())
     return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
   else {
     jboolean success = false;
-    ObjectLocker ol(p, THREAD);
-    if (*addr == e) { *addr = x; success = true; }
+    MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+    jlong val = Atomic::load(addr);
+    if (val == e) { Atomic::store(x, addr); success = true; }
     return success;
   }
+#endif
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
--- a/src/share/vm/runtime/arguments.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/arguments.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1572,7 +1572,7 @@
 
 void Arguments::select_gc() {
   if (!gc_selected()) {
-    ArgumentsExt::select_gc_ergonomically();
+    select_gc_ergonomically();
   }
 }
 
@@ -2067,7 +2067,7 @@
 }
 
 // Check consistency of GC selection
-bool Arguments::check_gc_consistency_user() {
+bool Arguments::check_gc_consistency() {
   check_gclog_consistency();
   bool status = true;
   // Ensure that the user has not selected conflicting sets
@@ -2233,7 +2233,7 @@
     FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
   }
 
-  status = status && check_gc_consistency_user();
+  status = status && check_gc_consistency();
   status = status && check_stack_pages();
 
   if (CMSIncrementalMode) {
@@ -2310,7 +2310,7 @@
                                         "G1ConcMarkStepDurationMillis");
     status = status && verify_interval(G1ConcRSHotCardLimit, 0, max_jubyte,
                                        "G1ConcRSHotCardLimit");
-    status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31,
+    status = status && verify_interval(G1ConcRSLogCacheSize, 0, 27,
                                        "G1ConcRSLogCacheSize");
     status = status && verify_interval(StringDeduplicationAgeThreshold, 1, markOopDesc::max_age,
                                        "StringDeduplicationAgeThreshold");
@@ -3837,8 +3837,8 @@
       CommandLineFlags::printFlags(tty, false);
       vm_exit(0);
     }
+    if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
 #if INCLUDE_NMT
-    if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
       // The launcher did not setup nmt environment variable properly.
       if (!MemTracker::check_launcher_nmt_support(tail)) {
         warning("Native Memory Tracking did not setup properly, using wrong launcher?");
@@ -3853,8 +3853,12 @@
       } else {
         vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
       }
+#else
+      jio_fprintf(defaultStream::error_stream(),
+        "Native Memory Tracking is not supported in this VM\n");
+      return JNI_ERR;
+#endif
     }
-#endif
 
 
 #ifndef PRODUCT
@@ -4006,7 +4010,7 @@
   set_shared_spaces_flags();
 
   // Check the GC selections again.
-  if (!ArgumentsExt::check_gc_consistency_ergo()) {
+  if (!check_gc_consistency()) {
     return JNI_EINVAL;
   }
 
--- a/src/share/vm/runtime/arguments.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/arguments.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -466,8 +466,7 @@
   static bool verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio);
 
   // Check for consistency in the selection of the garbage collector.
-  static bool check_gc_consistency_user();        // Check user-selected gc
-  static inline bool check_gc_consistency_ergo(); // Check ergonomic-selected gc
+  static bool check_gc_consistency();        // Check user-selected gc
   static void check_deprecated_gcs();
   static void check_deprecated_gc_flags();
   // Check consistecy or otherwise of VM argument settings
@@ -615,8 +614,4 @@
     UseParNewGC || UseSerialGC;
 }
 
-bool Arguments::check_gc_consistency_ergo() {
-  return check_gc_consistency_user();
-}
-
 #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP
--- a/src/share/vm/runtime/arguments_ext.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/arguments_ext.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -30,22 +30,12 @@
 
 class ArgumentsExt: AllStatic {
 public:
-  static inline void select_gc_ergonomically();
   static inline void set_gc_specific_flags();
-  static inline bool check_gc_consistency_ergo();
   static        void process_options(const JavaVMInitArgs* args) {}
 };
 
-void ArgumentsExt::select_gc_ergonomically() {
-  Arguments::select_gc_ergonomically();
-}
-
 void ArgumentsExt::set_gc_specific_flags() {
   Arguments::set_gc_specific_flags();
 }
 
-bool ArgumentsExt::check_gc_consistency_ergo() {
-  return Arguments::check_gc_consistency_ergo();
-}
-
 #endif // SHARE_VM_RUNTIME_ARGUMENTS_EXT_HPP
--- a/src/share/vm/runtime/basicLock.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/basicLock.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,9 @@
 
 void BasicLock::print_on(outputStream* st) const {
   st->print("monitor");
+  markOop moop = displaced_header();
+  if (moop != NULL)
+    moop->print_on(st);
 }
 
 void BasicLock::move_to(oop obj, BasicLock* dest) {
--- a/src/share/vm/runtime/deoptimization.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,25 +66,17 @@
 # include "vmreg_ppc.inline.hpp"
 #endif
 #ifdef COMPILER2
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined AD_MD_HPP
+# include AD_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/ad_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/ad_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/ad_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/ad_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/ad_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/ad_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/ad_ppc_64.hpp"
 #endif
 #endif // COMPILER2
--- a/src/share/vm/runtime/frame.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/frame.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,25 +31,17 @@
 #include "runtime/registerMap.hpp"
 #include "utilities/top.hpp"
 #ifdef COMPILER2
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined ADGLOBALS_MD_HPP
+# include ADGLOBALS_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/adGlobals_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/adGlobals_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/adGlobals_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/adGlobals_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/adGlobals_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/adGlobals_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/adGlobals_ppc_64.hpp"
 #endif
 #endif // COMPILER2
@@ -91,6 +83,15 @@
   // Constructors
   frame();
 
+#ifndef PRODUCT
+  // This is a generic constructor which is only used by pns() in debug.cpp.
+  // pns (i.e. print native stack) uses this constructor to create a starting
+  // frame for stack walking. The implementation of this constructor is platform
+  // dependent (i.e. SPARC doesn't need an 'fp' argument an will ignore it) but
+  // we want to keep the signature generic because pns() is shared code.
+  frame(void* sp, void* fp, void* pc);
+#endif
+
   // Accessors
 
   // pc: Returns the pc at which this frame will continue normally.
--- a/src/share/vm/runtime/globals.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/globals.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1494,7 +1494,7 @@
           "How much the GC can expand the eden by while the GC locker "     \
           "is active (as a percentage)")                                    \
                                                                             \
-  diagnostic(intx, GCLockerRetryAllocationCount, 2,                         \
+  diagnostic(uintx, GCLockerRetryAllocationCount, 2,                        \
           "Number of times to retry allocations when "                      \
           "blocked by the GC locker")                                       \
                                                                             \
@@ -2048,9 +2048,6 @@
           "Provide more detailed and expensive TLAB statistics "            \
           "(with PrintTLAB)")                                               \
                                                                             \
-  EMBEDDED_ONLY(product(bool, LowMemoryProtection, true,                    \
-          "Enable LowMemoryProtection"))                                    \
-                                                                            \
   product_pd(bool, NeverActAsServerClassMachine,                            \
           "Never act like a server-class machine")                          \
                                                                             \
--- a/src/share/vm/runtime/jniHandles.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/jniHandles.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -296,6 +296,7 @@
   block->_top  = 0;
   block->_next = NULL;
   block->_pop_frame_link = NULL;
+  block->_planned_capacity = block_size_in_oops;
   // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
   debug_only(block->_last = NULL);
   debug_only(block->_free_list = NULL);
@@ -529,6 +530,12 @@
   return result;
 }
 
+const size_t JNIHandleBlock::get_number_of_live_handles() {
+  CountHandleClosure counter;
+  oops_do(&counter);
+  return counter.count();
+}
+
 // This method is not thread-safe, i.e., must be called whule holding a lock on the
 // structure.
 long JNIHandleBlock::memory_usage() const {
--- a/src/share/vm/runtime/jniHandles.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/jniHandles.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,9 @@
   oop*            _free_list;                   // Handle free list
   int             _allocate_before_rebuild;     // Number of blocks to allocate before rebuilding free list
 
+  // Check JNI, "planned capacity" for current frame (or push/ensure)
+  size_t          _planned_capacity;
+
   #ifndef PRODUCT
   JNIHandleBlock* _block_list_link;             // Link for list below
   static JNIHandleBlock* _block_list;           // List of all allocated blocks (for debugging only)
@@ -152,6 +155,11 @@
   // Traversal of weak handles. Unreachable oops are cleared.
   void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
 
+  // Checked JNI support
+  void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; }
+  const size_t get_planned_capacity() { return _planned_capacity; }
+  const size_t get_number_of_live_handles();
+
   // Debugging
   bool chain_contains(jobject handle) const;    // Does this block or following blocks contain handle
   bool contains(jobject handle) const;          // Does this block contain handle
--- a/src/share/vm/runtime/mutexLocker.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/mutexLocker.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,7 +119,6 @@
 Mutex*   OldSets_lock                 = NULL;
 Monitor* RootRegionScan_lock          = NULL;
 Mutex*   MMUTracker_lock              = NULL;
-Mutex*   HotCardCache_lock            = NULL;
 
 Monitor* GCTaskManager_lock           = NULL;
 
@@ -135,6 +134,10 @@
 Mutex*   JfrThreadGroups_lock         = NULL;
 #endif
 
+#ifndef SUPPORTS_NATIVE_CX8
+Mutex*   UnsafeJlong_lock             = NULL;
+#endif
+
 #define MAX_NUM_MUTEX 128
 static Monitor * _mutex_array[MAX_NUM_MUTEX];
 static int _num_mutex;
@@ -196,7 +199,6 @@
     def(OldSets_lock               , Mutex  , leaf     ,   true );
     def(RootRegionScan_lock        , Monitor, leaf     ,   true );
     def(MMUTracker_lock            , Mutex  , leaf     ,   true );
-    def(HotCardCache_lock          , Mutex  , special  ,   true );
     def(EvacFailureStack_lock      , Mutex  , nonleaf  ,   true );
 
     def(StringDedupQueue_lock      , Monitor, leaf,        true );
@@ -280,12 +282,15 @@
 
 #ifdef INCLUDE_TRACE
   def(JfrMsg_lock                  , Monitor, leaf,        true);
-  def(JfrBuffer_lock               , Mutex,   nonleaf+1,   true);
-  def(JfrThreadGroups_lock         , Mutex,   nonleaf+1,   true);
-  def(JfrStream_lock               , Mutex,   nonleaf+2,   true);
-  def(JfrStacktrace_lock           , Mutex,   special,     true );
+  def(JfrBuffer_lock               , Mutex,   leaf,        true);
+  def(JfrThreadGroups_lock         , Mutex,   leaf,        true);
+  def(JfrStream_lock               , Mutex,   nonleaf,     true);
+  def(JfrStacktrace_lock           , Mutex,   special,     true);
 #endif
 
+#ifndef SUPPORTS_NATIVE_CX8
+  def(UnsafeJlong_lock             , Mutex,   special,     false);
+#endif
 }
 
 GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/src/share/vm/runtime/mutexLocker.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/mutexLocker.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,7 +137,6 @@
 extern Monitor* RootRegionScan_lock;             // used to notify that the CM threads have finished scanning the IM snapshot regions
 extern Mutex*   MMUTracker_lock;                 // protects the MMU
                                                  // tracker data structures
-extern Mutex*   HotCardCache_lock;               // protects the hot card cache
 
 extern Mutex*   Management_lock;                 // a lock used to serialize JVM management
 extern Monitor* Service_lock;                    // a lock used for service thread operation
@@ -151,6 +150,10 @@
 extern Mutex*   JfrThreadGroups_lock;            // protects JFR access to Thread Groups
 #endif
 
+#ifndef SUPPORTS_NATIVE_CX8
+extern Mutex*   UnsafeJlong_lock;                // provides Unsafe atomic updates to jlongs on platforms that don't support cx8
+#endif
+
 // A MutexLocker provides mutual exclusion with respect to a given mutex
 // for the scope which contains the locker.  The lock is an OS lock, not
 // an object lock, and the two do not interoperate.  Do not use Mutex-based
--- a/src/share/vm/runtime/os.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/os.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -159,7 +159,6 @@
   static void init_globals(void) {             // Called from init_globals() in init.cpp
     init_globals_ext();
   }
-  static void init_3(void);                    // Called at the end of vm init
 
   // File names are case-insensitive on windows only
   // Override me as needed
--- a/src/share/vm/runtime/stubRoutines.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/stubRoutines.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -99,29 +99,20 @@
 
   // Dependencies
   friend class StubGenerator;
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined STUBROUTINES_MD_HPP
+# include STUBROUTINES_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "stubRoutines_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "stubRoutines_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "stubRoutines_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "stubRoutines_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "stubRoutines_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "stubRoutines_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "stubRoutines_ppc_64.hpp"
 #endif
 
-
   static jint    _verify_oop_count;
   static address _verify_oop_subroutine_entry;
 
--- a/src/share/vm/runtime/thread.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/thread.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1465,6 +1465,7 @@
   _thread_stat = new ThreadStatistics();
   _blocked_on_compilation = false;
   _jni_active_critical = 0;
+  _pending_jni_exception_check_fn = NULL;
   _do_not_unlock_if_synchronized = false;
   _cached_monitor_info = NULL;
   _parker = Parker::Allocate(this) ;
@@ -3689,9 +3690,6 @@
       }
   }
 
-  // Give os specific code one last chance to start
-  os::init_3();
-
   create_vm_timer.end();
 #ifdef ASSERT
   _vm_complete = true;
--- a/src/share/vm/runtime/thread.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/thread.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -926,6 +926,9 @@
   // support for JNI critical regions
   jint    _jni_active_critical;                  // count of entries into JNI critical region
 
+  // Checked JNI: function name requires exception check
+  char* _pending_jni_exception_check_fn;
+
   // For deadlock detection.
   int _depth_first_number;
 
@@ -1408,6 +1411,12 @@
                           assert(_jni_active_critical >= 0,
                                  "JNI critical nesting problem?"); }
 
+  // Checked JNI, is the programmer required to check for exceptions, specify which function name
+  bool is_pending_jni_exception_check() const { return _pending_jni_exception_check_fn != NULL; }
+  void clear_pending_jni_exception_check() { _pending_jni_exception_check_fn = NULL; }
+  const char* get_pending_jni_exception_check() const { return _pending_jni_exception_check_fn; }
+  void set_pending_jni_exception_check(const char* fn_name) { _pending_jni_exception_check_fn = (char*) fn_name; }
+
   // For deadlock detection
   int depth_first_number() { return _depth_first_number; }
   void set_depth_first_number(int dfn) { _depth_first_number = dfn; }
--- a/src/share/vm/runtime/vframe.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/vframe.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
       if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
         if (monitor->owner_is_scalar_replaced()) {
           Klass* k = java_lang_Class::as_Klass(monitor->owner_klass());
+          // format below for lockbits matches this one.
           st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
         } else {
           oop obj = monitor->owner();
@@ -206,9 +207,10 @@
         // see if we have completed the lock or we are blocked trying to
         // acquire it - we can only be blocked if the monitor is inflated
 
+        markOop mark = NULL;
         const char *lock_state = "locked"; // assume we have the monitor locked
         if (!found_first_monitor && frame_count == 0) {
-          markOop mark = monitor->owner()->mark();
+          mark = monitor->owner()->mark();
           if (mark->has_monitor() &&
               ( // we have marked ourself as pending on this monitor
                 mark->monitor() == thread()->current_pending_monitor() ||
@@ -216,11 +218,19 @@
                 !mark->monitor()->is_entered(thread())
               )) {
             lock_state = "waiting to lock";
+          } else {
+            mark = NULL; // Disable printing below
           }
         }
+        print_locked_object_class_name(st, monitor->owner(), lock_state);
+        if (Verbose && mark != NULL) {
+          // match with format above, replacing "-" with " ".
+          st->print("\t  lockbits=");
+          mark->print_on(st);
+          st->cr();
+        }
 
         found_first_monitor = true;
-        print_locked_object_class_name(st, monitor->owner(), lock_state);
       }
     }
   }
@@ -578,10 +588,15 @@
       tty->print("( null )");
     } else {
       monitor->owner()->print_value();
-      tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner());
+      tty->print("(owner=" INTPTR_FORMAT ")", (address)monitor->owner());
     }
-    if (monitor->eliminated() && is_compiled_frame())
-      tty->print(" ( lock is eliminated )");
+    if (monitor->eliminated()) {
+      if(is_compiled_frame()) {
+        tty->print(" ( lock is eliminated in compiled frame )");
+      } else {
+        tty->print(" ( lock is eliminated, frame not compiled )");
+      }
+    }
     tty->cr();
     tty->print("\t  ");
     monitor->lock()->print_on(tty);
--- a/src/share/vm/runtime/vmStructs.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,7 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/macros.hpp"
+
 #ifdef TARGET_ARCH_x86
 # include "vmStructs_x86.hpp"
 #endif
@@ -167,6 +168,11 @@
 #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp"
 #include "gc_implementation/g1/vmStructs_g1.hpp"
 #endif // INCLUDE_ALL_GCS
+
+#if INCLUDE_TRACE
+ #include "runtime/vmStructs_trace.hpp"
+#endif
+
 #ifdef COMPILER2
 #include "opto/addnode.hpp"
 #include "opto/block.hpp"
@@ -186,25 +192,17 @@
 #include "opto/rootnode.hpp"
 #include "opto/subnode.hpp"
 #include "opto/vectornode.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
+#if defined ADGLOBALS_MD_HPP
+# include ADGLOBALS_MD_HPP
+#elif defined TARGET_ARCH_MODEL_x86_32
 # include "adfiles/adGlobals_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
+#elif defined TARGET_ARCH_MODEL_x86_64
 # include "adfiles/adGlobals_x86_64.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_sparc
+#elif defined TARGET_ARCH_MODEL_sparc
 # include "adfiles/adGlobals_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_zero
+#elif defined TARGET_ARCH_MODEL_zero
 # include "adfiles/adGlobals_zero.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_arm
-# include "adfiles/adGlobals_arm.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_32
-# include "adfiles/adGlobals_ppc_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_ppc_64
+#elif defined TARGET_ARCH_MODEL_ppc_64
 # include "adfiles/adGlobals_ppc_64.hpp"
 #endif
 #endif // COMPILER2
@@ -248,7 +246,6 @@
 typedef Hashtable<Klass*, mtClass>            KlassHashtable;
 typedef HashtableEntry<Klass*, mtClass>       KlassHashtableEntry;
 typedef TwoOopHashtable<Symbol*, mtClass>     SymbolTwoOopHashtable;
-typedef BinaryTreeDictionary<Metablock, FreeList<Metablock> > MetablockTreeDictionary;
 
 //--------------------------------------------------------------------------------
 // VM_STRUCTS
@@ -671,6 +668,7 @@
       static_field(SystemDictionary,            WK_KLASS(WeakReference_klass),                 Klass*)                               \
       static_field(SystemDictionary,            WK_KLASS(FinalReference_klass),                Klass*)                               \
       static_field(SystemDictionary,            WK_KLASS(PhantomReference_klass),              Klass*)                               \
+      static_field(SystemDictionary,            WK_KLASS(Cleaner_klass),                       Klass*)                               \
       static_field(SystemDictionary,            WK_KLASS(Finalizer_klass),                     Klass*)                               \
       static_field(SystemDictionary,            WK_KLASS(Thread_klass),                        Klass*)                               \
       static_field(SystemDictionary,            WK_KLASS(ThreadGroup_klass),                   Klass*)                               \
@@ -1289,11 +1287,8 @@
   volatile_nonstatic_field(FreeChunk,          _size,                                        size_t)                                 \
   nonstatic_field(FreeChunk,                   _next,                                        FreeChunk*)                             \
   nonstatic_field(FreeChunk,                   _prev,                                        FreeChunk*)                             \
-  nonstatic_field(FreeList<FreeChunk>,         _size,                                        size_t)                                 \
-  nonstatic_field(FreeList<Metablock>,         _size,                                        size_t)                                 \
-  nonstatic_field(FreeList<FreeChunk>,         _count,                                       ssize_t)                                \
-  nonstatic_field(FreeList<Metablock>,         _count,                                       ssize_t)                                \
-  nonstatic_field(MetablockTreeDictionary,     _total_size,                                  size_t)
+  nonstatic_field(AdaptiveFreeList<FreeChunk>, _size,                                        size_t)                                 \
+  nonstatic_field(AdaptiveFreeList<FreeChunk>, _count,                                       ssize_t)
 
 
 //--------------------------------------------------------------------------------
@@ -1385,6 +1380,8 @@
   /* unsigned short on Win32 */                                           \
   declare_unsigned_integer_type(u1)                                       \
   declare_unsigned_integer_type(u2)                                       \
+  declare_unsigned_integer_type(u4)                                       \
+  declare_unsigned_integer_type(u8)                                       \
   declare_unsigned_integer_type(unsigned)                                 \
                                                                           \
   /*****************************/                                         \
@@ -2165,14 +2162,8 @@
                                                                           \
   /* freelist */                                                          \
   declare_toplevel_type(FreeChunk*)                                       \
-  declare_toplevel_type(Metablock*)                                       \
-  declare_toplevel_type(FreeBlockDictionary<FreeChunk>*)                  \
-  declare_toplevel_type(FreeList<FreeChunk>*)                             \
-  declare_toplevel_type(FreeList<FreeChunk>)                              \
-  declare_toplevel_type(FreeBlockDictionary<Metablock>*)                  \
-  declare_toplevel_type(FreeList<Metablock>*)                             \
-  declare_toplevel_type(FreeList<Metablock>)                              \
-  declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)
+  declare_toplevel_type(AdaptiveFreeList<FreeChunk>*)                     \
+  declare_toplevel_type(AdaptiveFreeList<FreeChunk>)
 
 
 //--------------------------------------------------------------------------------
@@ -2914,6 +2905,11 @@
                 GENERATE_STATIC_VM_STRUCT_ENTRY)
 #endif // INCLUDE_ALL_GCS
 
+#if INCLUDE_TRACE
+  VM_STRUCTS_TRACE(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+                GENERATE_STATIC_VM_STRUCT_ENTRY)
+#endif
+
   VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                  GENERATE_STATIC_VM_STRUCT_ENTRY,
                  GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY,
@@ -2959,6 +2955,11 @@
               GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
 #endif // INCLUDE_ALL_GCS
 
+#if INCLUDE_TRACE
+  VM_TYPES_TRACE(GENERATE_VM_TYPE_ENTRY,
+              GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
+#endif
+
   VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY,
                GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
                GENERATE_OOP_VM_TYPE_ENTRY,
@@ -2994,6 +2995,10 @@
   VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY)
 #endif // INCLUDE_ALL_GCS
 
+#if INCLUDE_TRACE
+  VM_INT_CONSTANTS_TRACE(GENERATE_VM_INT_CONSTANT_ENTRY)
+#endif
+
   VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY,
                        GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
                        GENERATE_C1_VM_INT_CONSTANT_ENTRY,
@@ -3056,8 +3061,14 @@
 
   VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                 CHECK_STATIC_VM_STRUCT_ENTRY);
+
 #endif // INCLUDE_ALL_GCS
 
+#if INCLUDE_TRACE
+  VM_STRUCTS_TRACE(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
+                CHECK_STATIC_VM_STRUCT_ENTRY);
+#endif
+
   VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                  CHECK_STATIC_VM_STRUCT_ENTRY,
                  CHECK_NO_OP,
@@ -3096,8 +3107,14 @@
 
   VM_TYPES_G1(CHECK_VM_TYPE_ENTRY,
               CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
+
 #endif // INCLUDE_ALL_GCS
 
+#if INCLUDE_TRACE
+  VM_TYPES_TRACE(CHECK_VM_TYPE_ENTRY,
+              CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
+#endif
+
   VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY,
                CHECK_SINGLE_ARG_VM_TYPE_NO_OP,
                CHECK_SINGLE_ARG_VM_TYPE_NO_OP,
@@ -3160,6 +3177,12 @@
   debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT,
                            ENSURE_FIELD_TYPE_PRESENT));
 #endif // INCLUDE_ALL_GCS
+
+#if INCLUDE_TRACE
+  debug_only(VM_STRUCTS_TRACE(ENSURE_FIELD_TYPE_PRESENT,
+                           ENSURE_FIELD_TYPE_PRESENT));
+#endif
+
   debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT,
                             ENSURE_FIELD_TYPE_PRESENT,
                             CHECK_NO_OP,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/runtime/vmStructs_trace.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_RUNTIME_VMSTRUCTS_TRACE_HPP
+#define SHARE_VM_RUNTIME_VMSTRUCTS_TRACE_HPP
+
+#define VM_INT_CONSTANTS_TRACE(a)
+
+#define VM_STRUCTS_TRACE(a, b)
+
+#define VM_TYPES_TRACE(a, b)
+
+
+#endif // SHARE_VM_RUNTIME_VMSTRUCTS_TRACE_HPP
--- a/src/share/vm/runtime/vm_version.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/runtime/vm_version.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,17 +180,17 @@
                  AIX_ONLY("aix")                 \
                  BSD_ONLY("bsd")
 
+#ifndef CPU
 #ifdef ZERO
 #define CPU      ZERO_LIBARCH
 #else
 #define CPU      IA32_ONLY("x86")                \
                  IA64_ONLY("ia64")               \
                  AMD64_ONLY("amd64")             \
-                 ARM_ONLY("arm")                 \
-                 PPC32_ONLY("ppc")               \
                  PPC64_ONLY("ppc64")             \
                  SPARC_ONLY("sparc")
 #endif // ZERO
+#endif
 
 const char *Abstract_VM_Version::vm_platform_string() {
   return OS "-" CPU;
@@ -251,12 +251,6 @@
   #ifndef FLOAT_ARCH
     #if defined(__SOFTFP__)
       #define FLOAT_ARCH_STR "-sflt"
-    #elif defined(E500V2)
-      #define FLOAT_ARCH_STR "-e500v2"
-    #elif defined(ARM)
-      #define FLOAT_ARCH_STR "-vfp"
-    #elif defined(PPC32)
-      #define FLOAT_ARCH_STR "-hflt"
     #else
       #define FLOAT_ARCH_STR ""
     #endif
--- a/src/share/vm/services/classLoadingService.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/services/classLoadingService.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 @@
       len = name->utf8_length();                    \
     }                                               \
     HS_DTRACE_PROBE4(hotspot, class__##type,        \
-      data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), (shared)); \
+      data, len, (void *)(clss)->class_loader(), (shared)); \
   }
 
 #else /* USDT2 */
--- a/src/share/vm/services/management.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/services/management.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -155,11 +155,14 @@
     // Load and initialize the sun.management.Agent class
     // invoke startAgent method to start the management server
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
-    Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(),
+    Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_management_Agent(),
                                                    loader,
                                                    Handle(),
-                                                   true,
-                                                   CHECK);
+                                                   THREAD);
+    if (k == NULL) {
+      vm_exit_during_initialization("Management agent initialization failure: "
+          "class sun.management.Agent not found.");
+    }
     instanceKlassHandle ik (THREAD, k);
 
     JavaValue result(T_VOID);
--- a/src/share/vm/trace/trace.xml	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/trace/trace.xml	Wed Apr 22 06:24:15 2015 +0100
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -352,6 +352,12 @@
       <value type="UTF8" field="name" label="Name" />
     </event>
 
+    <event id="AllocationRequiringGC" path="vm/gc/detailed/allocation_requiring_gc" label="Allocation Requiring GC"
+           has_thread="true" has_stacktrace="true"  is_instant="true">
+      <value type="UINT" field="gcId"  label="Pending GC ID" relation="GC_ID" />
+      <value type="BYTES64" field="size" label="Allocation Size" />
+    </event>
+
     <!-- Compiler events -->
 
     <event id="Compilation" path="vm/compiler/compilation" label="Compilation"
--- a/src/share/vm/utilities/accessFlags.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/accessFlags.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,8 @@
   JVM_ACC_IS_OLD                  = 0x00010000,     // RedefineClasses() has replaced this method
   JVM_ACC_IS_OBSOLETE             = 0x00020000,     // RedefineClasses() has made method obsolete
   JVM_ACC_IS_PREFIXED_NATIVE      = 0x00040000,     // JVMTI has prefixed this native method
-  JVM_ACC_ON_STACK                = 0x00080000,     // RedefinedClasses() is used on the stack
+  JVM_ACC_ON_STACK                = 0x00080000,     // RedefineClasses() was used on the stack
+  JVM_ACC_IS_DELETED              = 0x00008000,     // RedefineClasses() has deleted this method
 
   // Klass* flags
   JVM_ACC_HAS_MIRANDA_METHODS     = 0x10000000,     // True if this class has miranda methods in it's vtable
@@ -131,6 +132,7 @@
   bool has_jsrs                () const { return (_flags & JVM_ACC_HAS_JSRS               ) != 0; }
   bool is_old                  () const { return (_flags & JVM_ACC_IS_OLD                 ) != 0; }
   bool is_obsolete             () const { return (_flags & JVM_ACC_IS_OBSOLETE            ) != 0; }
+  bool is_deleted              () const { return (_flags & JVM_ACC_IS_DELETED             ) != 0; }
   bool is_prefixed_native      () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE     ) != 0; }
 
   // Klass* flags
@@ -196,6 +198,7 @@
   void set_has_jsrs()                  { atomic_set_bits(JVM_ACC_HAS_JSRS);                }
   void set_is_old()                    { atomic_set_bits(JVM_ACC_IS_OLD);                  }
   void set_is_obsolete()               { atomic_set_bits(JVM_ACC_IS_OBSOLETE);             }
+  void set_is_deleted()                { atomic_set_bits(JVM_ACC_IS_DELETED);              }
   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);       }
--- a/src/share/vm/utilities/debug.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/debug.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -666,6 +666,13 @@
   tty->print_cr("  pm(int pc)    - print Method* given compiled PC");
   tty->print_cr("  findm(intptr_t pc) - finds Method*");
   tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
+  tty->print_cr("  pns(void* sp, void* fp, void* pc)  - print native (i.e. mixed) stack trace. E.g.");
+  tty->print_cr("                   pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
+  tty->print_cr("                   pns($sp, $ebp, $pc) on Linux/x86 or");
+  tty->print_cr("                   pns($sp, 0, $pc)    on Linux/ppc64 or");
+  tty->print_cr("                   pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
+  tty->print_cr("                 - in gdb do 'set overload-resolution off' before calling pns()");
+  tty->print_cr("                 - in dbx do 'frame 1' before calling pns()");
 
   tty->print_cr("misc.");
   tty->print_cr("  flush()       - flushes the log file");
@@ -678,3 +685,56 @@
 }
 
 #endif // !PRODUCT
+
+void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size) {
+
+  // see if it's a valid frame
+  if (fr.pc()) {
+    st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
+
+    int count = 0;
+    while (count++ < StackPrintLimit) {
+      fr.print_on_error(st, buf, buf_size);
+      st->cr();
+      // Compiled code may use EBP register on x86 so it looks like
+      // non-walkable C frame. Use frame.sender() for java frames.
+      if (t && t->is_Java_thread()) {
+        // Catch very first native frame by using stack address.
+        // For JavaThread stack_base and stack_size should be set.
+        if (!t->on_local_stack((address)(fr.real_fp() + 1))) {
+          break;
+        }
+        if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) {
+          RegisterMap map((JavaThread*)t, false); // No update
+          fr = fr.sender(&map);
+        } else {
+          fr = os::get_sender_for_C_frame(&fr);
+        }
+      } else {
+        // is_first_C_frame() does only simple checks for frame pointer,
+        // it will pass if java compiled code has a pointer in EBP.
+        if (os::is_first_C_frame(&fr)) break;
+        fr = os::get_sender_for_C_frame(&fr);
+      }
+    }
+
+    if (count > StackPrintLimit) {
+      st->print_cr("...<more frames>...");
+    }
+
+    st->cr();
+  }
+}
+
+#ifndef PRODUCT
+
+extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack
+  Command c("pns");
+  static char buf[O_BUFLEN];
+  Thread* t = ThreadLocalStorage::get_thread_slow();
+  // Call generic frame constructor (certain arguments may be ignored)
+  frame fr(sp, fp, pc);
+  print_native_stack(tty, fr, t, buf, sizeof(buf));
+}
+
+#endif // !PRODUCT
--- a/src/share/vm/utilities/debug.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/debug.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -265,4 +265,7 @@
 void pd_ps(frame f);
 void pd_obfuscate_location(char *buf, size_t buflen);
 
+class outputStream;
+void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size);
+
 #endif // SHARE_VM_UTILITIES_DEBUG_HPP
--- a/src/share/vm/utilities/defaultStream.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/defaultStream.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -41,6 +41,8 @@
 
   void init();
   void init_log();
+  fileStream* open_file(const char* log_name);
+  void start_log();
   void finish_log();
   void finish_log_on_error(char *buf, int buflen);
  public:
--- a/src/share/vm/utilities/globalDefinitions_gcc.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,14 +44,6 @@
 #endif // SOLARIS
 
 #include <math.h>
-#ifndef FP_PZERO
-// Linux doesn't have positive/negative zero
-#define FP_PZERO FP_ZERO
-#endif
-#if (!defined fpclass) && ((!defined SPARC) || (!defined SOLARIS))
-#define fpclass fpclassify
-#endif
-
 #include <time.h>
 #include <fcntl.h>
 #include <dlfcn.h>
@@ -220,7 +212,7 @@
 
 #define DEBUG_EXCEPTION ::abort();
 
-#ifdef ARM
+#ifdef ARM32
 #ifdef SOLARIS
 #define BREAKPOINT __asm__ volatile (".long 0xe1200070")
 #else
--- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,9 @@
 
 
 # include <ctype.h>
+#define __USE_LEGACY_PROTOTYPES__
 # include <dirent.h>
+#undef __USE_LEGACY_PROTOTYPES__
 # include <string.h>
 # include <strings.h>     // for bsd'isms
 # include <stdarg.h>
@@ -46,15 +48,6 @@
 # include <ieeefp.h>
 #endif
 # include <math.h>
-#ifdef LINUX
-#ifndef FP_PZERO
-  // Linux doesn't have positive/negative zero
-  #define FP_PZERO FP_ZERO
-#endif
-#ifndef fpclass
-  #define fpclass fpclassify
-#endif
-#endif
 # include <time.h>
 # include <fcntl.h>
 # include <dlfcn.h>
--- a/src/share/vm/utilities/globalDefinitions_xlc.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/globalDefinitions_xlc.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -41,14 +41,6 @@
 #include <wchar.h>
 
 #include <math.h>
-#ifndef FP_PZERO
-// Linux doesn't have positive/negative zero
-#define FP_PZERO FP_ZERO
-#endif
-#if (!defined fpclass)
-#define fpclass fpclassify
-#endif
-
 #include <time.h>
 #include <fcntl.h>
 #include <dlfcn.h>
--- a/src/share/vm/utilities/macros.hpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/macros.hpp	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -392,7 +392,6 @@
 #define NOT_E500V2(code) code
 #endif
 
-
 #ifdef ARM
 #define ARM_ONLY(code) code
 #define NOT_ARM(code)
@@ -401,6 +400,14 @@
 #define NOT_ARM(code) code
 #endif
 
+#ifdef ARM32
+#define ARM32_ONLY(code) code
+#define NOT_ARM32(code)
+#else
+#define ARM32_ONLY(code)
+#define NOT_ARM32(code) code
+#endif
+
 #ifdef JAVASE_EMBEDDED
 #define EMBEDDED_ONLY(code) code
 #define NOT_EMBEDDED(code)
--- a/src/share/vm/utilities/ostream.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/ostream.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -370,7 +370,6 @@
 
 #define EXTRACHARLEN   32
 #define CURRENTAPPX    ".current"
-#define FILENAMEBUFLEN  1024
 // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
 char* get_datetime_string(char *buf, size_t len) {
   os::local_time_string(buf, len);
@@ -404,7 +403,6 @@
     buffer_length = strlen(log_name) + 1;
   }
 
-  // const char* star = strchr(basename, '*');
   const char* pts = strstr(basename, "%p");
   int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
 
@@ -419,6 +417,11 @@
     buffer_length += strlen(tms);
   }
 
+  // File name is too long.
+  if (buffer_length > JVM_MAXPATHLEN) {
+    return NULL;
+  }
+
   // Create big enough buffer.
   char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
 
@@ -492,46 +495,88 @@
 void test_loggc_filename() {
   int pid;
   char  tms[32];
-  char  i_result[FILENAMEBUFLEN];
+  char  i_result[JVM_MAXPATHLEN];
   const char* o_result;
   get_datetime_string(tms, sizeof(tms));
   pid = os::current_process_id();
 
   // test.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms);
   o_result = make_log_name_internal("test.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 
   // test-%t-%p.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
   o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 
   // test-%t%p.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
   o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 
   // %p%t.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
   o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 
   // %p-test.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid);
   o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 
   // %t.log
-  jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms);
+  jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms);
   o_result = make_log_name_internal("%t.log", NULL, pid, tms);
   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
+
+  {
+    // longest filename
+    char longest_name[JVM_MAXPATHLEN];
+    memset(longest_name, 'a', sizeof(longest_name));
+    longest_name[JVM_MAXPATHLEN - 1] = '\0';
+    o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+    assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result));
+    FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
+  }
+
+  {
+    // too long file name
+    char too_long_name[JVM_MAXPATHLEN + 100];
+    int too_long_length = sizeof(too_long_name);
+    memset(too_long_name, 'a', too_long_length);
+    too_long_name[too_long_length - 1] = '\0';
+    o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms);
+    assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result));
+  }
+
+  {
+    // too long with timestamp
+    char longest_name[JVM_MAXPATHLEN];
+    memset(longest_name, 'a', JVM_MAXPATHLEN);
+    longest_name[JVM_MAXPATHLEN - 3] = '%';
+    longest_name[JVM_MAXPATHLEN - 2] = 't';
+    longest_name[JVM_MAXPATHLEN - 1] = '\0';
+    o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+    assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result));
+  }
+
+  {
+    // too long with pid
+    char longest_name[JVM_MAXPATHLEN];
+    memset(longest_name, 'a', JVM_MAXPATHLEN);
+    longest_name[JVM_MAXPATHLEN - 3] = '%';
+    longest_name[JVM_MAXPATHLEN - 2] = 'p';
+    longest_name[JVM_MAXPATHLEN - 1] = '\0';
+    o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+    assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
+  }
 }
 #endif // PRODUCT
 
@@ -640,9 +685,16 @@
   _bytes_written = 0L;
   _file_name = make_log_name(file_name, NULL);
 
+  if (_file_name == NULL) {
+    warning("Cannot open file %s: file name is too long.\n", file_name);
+    _need_close = false;
+    UseGCLogFileRotation = false;
+    return;
+  }
+
   // gc log file rotation
   if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
-    char tempbuf[FILENAMEBUFLEN];
+    char tempbuf[JVM_MAXPATHLEN];
     jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
     _file = fopen(tempbuf, "w");
   } else {
@@ -674,10 +726,10 @@
 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
 // must be synchronized.
 void gcLogFileStream::rotate_log(bool force, outputStream* out) {
-  char time_msg[FILENAMEBUFLEN];
+  char time_msg[O_BUFLEN];
   char time_str[EXTRACHARLEN];
-  char current_file_name[FILENAMEBUFLEN];
-  char renamed_file_name[FILENAMEBUFLEN];
+  char current_file_name[JVM_MAXPATHLEN];
+  char renamed_file_name[JVM_MAXPATHLEN];
 
   if (!should_rotate(force)) {
     return;
@@ -716,12 +768,15 @@
   // have a form of extended_filename.<i>.current where i is the current rotation
   // file number. After it reaches max file size, the file will be saved and renamed
   // with .current removed from its tail.
-  size_t filename_len = strlen(_file_name);
   if (_file != NULL) {
-    jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d",
+    jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
                  _file_name, _cur_file_num);
-    jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
-                 _file_name, _cur_file_num);
+    int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
+                              "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
+    if (result >= JVM_MAXPATHLEN) {
+      warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+      return;
+    }
 
     const char* msg = force ? "GC log rotation request has been received."
                             : "GC log file has reached the maximum size.";
@@ -760,19 +815,23 @@
 
   _cur_file_num++;
   if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
-  jio_snprintf(current_file_name,  filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
+  int result = jio_snprintf(current_file_name,  JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX,
                _file_name, _cur_file_num);
+  if (result >= JVM_MAXPATHLEN) {
+    warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+    return;
+  }
+
   _file = fopen(current_file_name, "w");
 
   if (_file != NULL) {
     _bytes_written = 0L;
     _need_close = true;
     // reuse current_file_name for time_msg
-    jio_snprintf(current_file_name, filename_len + EXTRACHARLEN,
+    jio_snprintf(current_file_name, JVM_MAXPATHLEN,
                  "%s.%d", _file_name, _cur_file_num);
     jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
-                           os::local_time_string((char *)time_str, sizeof(time_str)),
-                           current_file_name);
+                 os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
     write(time_msg, strlen(time_msg));
 
     if (out != NULL) {
@@ -820,32 +879,64 @@
   return _log_file != NULL;
 }
 
+fileStream* defaultStream::open_file(const char* log_name) {
+  const char* try_name = make_log_name(log_name, NULL);
+  if (try_name == NULL) {
+    warning("Cannot open file %s: file name is too long.\n", log_name);
+    return NULL;
+  }
+
+  fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+  FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
+  if (file->is_open()) {
+    return file;
+  }
+
+  // Try again to open the file in the temp directory.
+  delete file;
+  char warnbuf[O_BUFLEN*2];
+  jio_snprintf(warnbuf, sizeof(warnbuf), "Warning:  Cannot open log file: %s\n", log_name);
+  // Note:  This feature is for maintainer use only.  No need for L10N.
+  jio_print(warnbuf);
+  try_name = make_log_name(log_name, os::get_temp_directory());
+  if (try_name == NULL) {
+    warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
+    return NULL;
+  }
+
+  jio_snprintf(warnbuf, sizeof(warnbuf),
+               "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
+  jio_print(warnbuf);
+
+  file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+  FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
+  if (file->is_open()) {
+    return file;
+  }
+
+  delete file;
+  return NULL;
+}
+
 void defaultStream::init_log() {
   // %%% Need a MutexLocker?
   const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
-  const char* try_name = make_log_name(log_name, NULL);
-  fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
-  if (!file->is_open()) {
-    // Try again to open the file.
-    char warnbuf[O_BUFLEN*2];
-    jio_snprintf(warnbuf, sizeof(warnbuf),
-                 "Warning:  Cannot open log file: %s\n", try_name);
-    // Note:  This feature is for maintainer use only.  No need for L10N.
-    jio_print(warnbuf);
-    FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
-    try_name = make_log_name(log_name, os::get_temp_directory());
-    jio_snprintf(warnbuf, sizeof(warnbuf),
-                 "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
-    jio_print(warnbuf);
-    delete file;
-    file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+  fileStream* file = open_file(log_name);
+
+  if (file != NULL) {
+    _log_file = file;
+    _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
+    start_log();
+  } else {
+    // and leave xtty as NULL
+    LogVMOutput = false;
+    DisplayVMOutput = true;
+    LogCompilation = false;
   }
-  FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
+}
 
-  if (file->is_open()) {
-    _log_file = file;
-    xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
-    _outer_xmlStream = xs;
+void defaultStream::start_log() {
+  xmlStream*xs = _outer_xmlStream;
     if (this == tty)  xtty = xs;
     // Write XML header.
     xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
@@ -900,13 +991,6 @@
     xs->head("tty");
     // All further non-markup text gets copied to the tty:
     xs->_text = this;  // requires friend declaration!
-  } else {
-    delete(file);
-    // and leave xtty as NULL
-    LogVMOutput = false;
-    DisplayVMOutput = true;
-    LogCompilation = false;
-  }
 }
 
 // finish_log() is called during normal VM shutdown. finish_log_on_error() is
--- a/src/share/vm/utilities/vmError.cpp	Fri Feb 27 09:59:29 2015 +0000
+++ b/src/share/vm/utilities/vmError.cpp	Wed Apr 22 06:24:15 2015 +0100
@@ -22,6 +22,7 @@
  *
  */
 
+#include <fcntl.h>
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc_interface/collectedHeap.hpp"
@@ -588,7 +589,7 @@
 
   STEP(120, "(printing native stack)" )
 
-     if (_verbose) {
+   if (_verbose) {
      if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
        // We have printed the native stack in platform-specific code
        // Windows/x64 needs special handling.
@@ -596,43 +597,7 @@
        frame fr = _context ? os::fetch_frame_from_context(_context)
                            : os::current_frame();
 
-       // see if it's a valid frame
-       if (fr.pc()) {
-          st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
-
-
-          int count = 0;
-          while (count++ < StackPrintLimit) {
-             fr.print_on_error(st, buf, sizeof(buf));
-             st->cr();
-             // Compiled code may use EBP register on x86 so it looks like
-             // non-walkable C frame. Use frame.sender() for java frames.
-             if (_thread && _thread->is_Java_thread()) {
-               // Catch very first native frame by using stack address.
-               // For JavaThread stack_base and stack_size should be set.
-               if (!_thread->on_local_stack((address)(fr.sender_sp() + 1))) {
-                 break;
-               }
-               if (fr.is_java_frame()) {
-                 RegisterMap map((JavaThread*)_thread, false); // No update
-                 fr = fr.sender(&map);
-               } else {
-                 fr = os::get_sender_for_C_frame(&fr);
-               }
-             } else {
-               // is_first_C_frame() does only simple checks for frame pointer,
-               // it will pass if java compiled code has a pointer in EBP.
-               if (os::is_first_C_frame(&fr)) break;
-               fr = os::get_sender_for_C_frame(&fr);
-             }
-          }
-
-          if (count > StackPrintLimit) {
-             st->print_cr("...<more frames>...");
-          }
-
-          st->cr();
-       }
+       print_native_stack(st, fr, _thread, buf, sizeof(buf));
      }
    }
 
@@ -854,7 +819,8 @@
 static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
   int fd = -1;
   if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
-    fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
+    // the O_EXCL flag will cause the open to fail if the file exists
+    fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
   }
   return fd;
 }
--- a/test/TEST.groups	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/TEST.groups	Wed Apr 22 06:24:15 2015 +0100
@@ -171,6 +171,7 @@
   gc/g1/TestShrinkAuxiliaryData20.java \
   gc/g1/TestShrinkAuxiliaryData25.java \
   gc/g1/TestShrinkAuxiliaryData30.java \
+  gc/survivorAlignment \
   runtime/InternalApi/ThreadCpuTimesDeadlock.java \
   serviceability/threads/TestFalseDeadLock.java \
   serviceability/jvmti/GetObjectSizeOverflow.java \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/escapeAnalysis/TestEscapeThroughInvoke.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8073956
+ * @summary Tests C2 EA with allocated object escaping through a call.
+ * @run main/othervm -XX:CompileCommand=dontinline,TestEscapeThroughInvoke::create TestEscapeThroughInvoke
+ */
+public class TestEscapeThroughInvoke {
+    private A a;
+
+    public static void main(String[] args) {
+        TestEscapeThroughInvoke test = new TestEscapeThroughInvoke();
+        test.a = new A(42);
+        // Make sure run gets compiled by C2
+        for (int i = 0; i < 100_000; ++i) {
+            test.run();
+        }
+    }
+
+    private void run() {
+        // Allocate something to trigger EA
+        new Object();
+        // Create a new escaping instance of A and
+        // verify that it is always equal to 'a.saved'.
+        A escapingA = create(42);
+        a.check(escapingA);
+    }
+
+    // Create and return a new instance of A that escaped through 'A::saveInto'.
+    // The 'dummy' parameters are needed to avoid EA skipping the methods.
+    private A create(Integer dummy) {
+        A result = new A(dummy);
+        result.saveInto(a, dummy); // result escapes into 'a' here
+        return result;
+    }
+}
+
+class A {
+    private A saved;
+
+    public A(Integer dummy) { }
+
+    public void saveInto(A other, Integer dummy) {
+        other.saved = this;
+    }
+
+    public void check(A other) {
+        if (this.saved != other) {
+            throw new RuntimeException("TEST FAILED: Objects not equal.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/inlining/DefaultMethodsDependencies.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8069263
+ * @summary Deoptimization between array allocation and arraycopy may result in non initialized array
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileOnly=DefaultMethodsDependencies::test -XX:CompileOnly=DefaultMethodsDependencies$I2::m1 DefaultMethodsDependencies
+ *
+ */
+
+public class DefaultMethodsDependencies {
+
+    interface I1 {
+        void m1();
+        // triggers processing of default methods in C1
+        default void m2() {
+        }
+    }
+
+    interface I2 extends I1 {
+        // added to C2 as default method
+        default void m1() {
+        }
+    }
+
+    static abstract class C1 implements I1 {
+    }
+
+    static class C2 extends C1 implements I2 {
+    }
+
+    static void test(C1 obj) {
+        obj.m1();
+    }
+
+    static public void main(String[] args) {
+        C2 obj = new C2();
+        for (int i = 0; i < 20000; i++) {
+            test(obj);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/loopopts/ConstFPVectorization.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8074869
+ * @summary C2 code generator can replace -0.0f with +0.0f on Linux
+ * @run main ConstFPVectorization 8
+ * @author volker.simonis@gmail.com
+ *
+ */
+
+public class ConstFPVectorization {
+
+    static float[] f = new float[16];
+    static double[] d = new double[16];
+
+    static void floatLoop(int count) {
+        for (int i = 0; i < count; i++) {
+            f[i] = -0.0f;
+        }
+    }
+
+    static void doubleLoop(int count) {
+        for (int i = 0; i < count; i++) {
+            d[i] = -0.0d;
+        }
+    }
+
+    public static void main(String args[]) {
+        for (int i = 0; i < 10_000; i++) {
+            floatLoop(Integer.parseInt(args[0]));
+            doubleLoop(Integer.parseInt(args[0]));
+        }
+        for (int i = 0; i < Integer.parseInt(args[0]); i++) {
+            if (Float.floatToRawIntBits(f[i]) != Float.floatToRawIntBits(-0.0f))
+                throw new Error("Float error at index " + i);
+            if (Double.doubleToRawLongBits(d[i]) != Double.doubleToRawLongBits(-0.0d))
+                throw new Error("Double error at index " + i);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/loopopts/CountedLoopProblem.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8072753
+ * @summary Inner loop induction variable increment occurs before compare which causes integer overflow
+ * @run main/othervm CountedLoopProblem
+ *
+ */
+
+import java.util.*;
+
+public class CountedLoopProblem {
+    public static void main(String[] args) throws Exception {
+        Random r = new Random(42);
+        int x = 0;
+        StringBuilder sb = new StringBuilder();
+        for(int i = 0; i < 1000000; ++i) {
+            int v = Math.abs(r.nextInt());
+            sb.append('+').append(v).append('\n');
+            x += v;
+            // To trigger the problem we must OSR in the following loop
+            // To make the problem 100% reproducible run with -XX:-TieredCompilation -XX:OSROnlyBCI=62
+            while(x < 0) x += 1000000000;
+            sb.append('=').append(x).append('\n');
+        }
+        if (sb.toString().hashCode() != 0xaba94591) {
+            throw new Exception("Unexpected result");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/stringopts/TestOptimizeStringConcat.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 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
+ * @bug 8068909
+ * @key regression
+ * @summary test that string optimizations produce code, that doesn't lead to a crash.
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat
+ * @author axel.siebenborn@sap.com
+ */
+public class TestOptimizeStringConcat {
+
+    static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) {
+        String rc = null;
+
+        int maxchar = 99999;
+        int minchar = 1;
+        if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) {
+            rc = "internal error";
+        } else {
+            if (value == null) {
+                rc = "the value null is not allowed, it is missing";
+            } else if (value != null && minchar > 0 && value.trim().equals("")) {
+                rc = "the value must not be empty";
+            } else if (value != null) {
+                if (value.length() < minchar || value.length() > maxchar) {
+                    if (rc == null) {
+                        rc = "the value length must be between +minchar+ and +maxchar";
+                    }
+                }
+                char[] _value = value.toCharArray();
+                boolean dotfound = false;
+                int i = 1;
+                if (_value[i] == '.' && !dotfound) {
+                    dotfound = true;
+                } else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) {
+                    if (rc == null) {
+                        rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+                    } else {
+                        rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+                    }
+                } else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) {
+                    if (rc == null) {
+                        rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+                    } else {
+                        rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+                    }
+                }
+            }
+        }
+
+        if (rc != null) {
+            System.out.println(logmsg + " ==> " + rc);
+            return false;
+        }
+        return true;
+    }
+
+    public static void main(String[] args) {
+        boolean failed = false;
+        for (int i = 0; i < 10000; i++) {
+            failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition");
+            failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition");
+            failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition");
+        }
+        System.out.println(failed);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/types/TestMeetExactConstantArrays.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8075587
+ * @summary meet of 2 constant arrays result in bottom
+ * @run main/othervm TestMeetExactConstantArrays
+ *
+ */
+
+public class TestMeetExactConstantArrays {
+    public abstract static class NumbersHolder {
+        public Number[] getNumbers() {
+            return null;
+        }
+    }
+
+    public static class IntegersHolder extends NumbersHolder {
+        private final static Integer integers[] = { new Integer(1) };
+
+        public Number[] getNumbers() {
+            return integers;
+        }
+    }
+
+    public static class LongsHolder extends NumbersHolder {
+        private final static Long longs[] = { new Long(1) };
+
+        public Number[] getNumbers() {
+            return longs;
+        }
+    }
+
+    public static final void loopNumbers(NumbersHolder numbersHolder) {
+        Number[] numbers = numbersHolder.getNumbers();
+        for (int i = 0; i < numbers.length; i++) {
+            numbers[i].longValue();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        for (int i = 0; i < 10000; i++) {
+            IntegersHolder integersHolder = new IntegersHolder();
+            LongsHolder longsHolder = new LongsHolder();
+            loopNumbers(integersHolder);
+            loopNumbers(longsHolder);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+
+/**
+ * @test
+ * @bug 8031323
+ * @summary Verify SurvivorAlignmentInBytes option processing.
+ * @library /testlibrary
+ * @requires vm.opt.SurvivorAlignmentInBytes == null
+ *           & vm.opt.ObjectAlignmentInBytes == null
+ *           & vm.opt.UnlockExperimentalVMOptions == null
+ *           & (vm.opt.IgnoreUnrecognizedVMOptions == null
+ *              | vm.opt.IgnoreUnrecognizedVMOptions == "false")
+ * @run main TestSurvivorAlignmentInBytesOption
+ */
+public class TestSurvivorAlignmentInBytesOption {
+    public static void main(String args[]) throws Throwable {
+        String optionName = "SurvivorAlignmentInBytes";
+        String unlockExperimentalVMOpts = "UnlockExperimentalVMOptions";
+        String optionIsExperimental
+                = CommandLineOptionTest.getExperimentalOptionErrorMessage(
+                optionName);
+        String valueIsTooSmall= ".*SurvivorAlignmentInBytes=.*must be greater"
+                + " than ObjectAlignmentInBytes.*";
+        String mustBePowerOf2 = ".*SurvivorAlignmentInBytes=.*must be "
+                + "power of 2.*";
+
+        // Verify that without -XX:+UnlockExperimentalVMOptions usage of
+        // SurvivorAlignmentInBytes option will cause JVM startup failure
+        // with the warning message saying that that option is experimental.
+        CommandLineOptionTest.verifyJVMStartup(
+                new String[]{optionIsExperimental}, null, ExitCode.FAIL, false,
+                "-XX:-UnlockExperimentalVMOptions",
+                CommandLineOptionTest.prepareBooleanFlag(
+                        unlockExperimentalVMOpts, false),
+                CommandLineOptionTest.prepareNumericFlag(optionName, 64));
+
+        // Verify that with -XX:+UnlockExperimentalVMOptions passed to JVM
+        // usage of SurvivorAlignmentInBytes option won't cause JVM startup
+        // failure.
+        CommandLineOptionTest.verifyJVMStartup(
+                null, new String[]{optionIsExperimental}, ExitCode.OK, false,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        unlockExperimentalVMOpts, true),
+                CommandLineOptionTest.prepareNumericFlag(optionName, 64));
+
+        // Verify that if specified SurvivorAlignmentInBytes is lower then
+        // ObjectAlignmentInBytes, then the JVM startup will fail with
+        // appropriate error message.
+        CommandLineOptionTest.verifyJVMStartup(
+                new String[]{valueIsTooSmall}, null, ExitCode.FAIL, false,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        unlockExperimentalVMOpts, true),
+                CommandLineOptionTest.prepareNumericFlag(optionName, 2));
+
+        // Verify that if specified SurvivorAlignmentInBytes value is not
+        // a power of 2 then the JVM startup will fail with appropriate error
+        // message.
+        CommandLineOptionTest.verifyJVMStartup(
+                new String[]{mustBePowerOf2}, null, ExitCode.FAIL, false,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        unlockExperimentalVMOpts, true),
+                CommandLineOptionTest.prepareNumericFlag(optionName, 127));
+
+        // Verify that if SurvivorAlignmentInBytes has correct value, then
+        // the JVM will be started without errors.
+        CommandLineOptionTest.verifyJVMStartup(
+                null, new String[]{".*SurvivorAlignmentInBytes.*"},
+                ExitCode.OK, false,
+                CommandLineOptionTest.prepareBooleanFlag(
+                        unlockExperimentalVMOpts, true),
+                CommandLineOptionTest.prepareNumericFlag(optionName, 128));
+
+        // Verify that we can setup different SurvivorAlignmentInBytes values.
+        for (int alignment = 32; alignment <= 128; alignment *= 2) {
+            CommandLineOptionTest.verifyOptionValue(optionName,
+                    Integer.toString(alignment),
+                    CommandLineOptionTest.prepareBooleanFlag(
+                            unlockExperimentalVMOpts, true),
+                    CommandLineOptionTest.prepareNumericFlag(
+                            optionName, alignment));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestG1TraceReclaimDeadHumongousObjectsAtYoungGC.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 TestG1TraceReclaimDeadHumongousObjectsAtYoungGC
+ * @bug 8058801
+ * @summary Ensure that the output for a G1TraceReclaimDeadHumongousObjectsAtYoungGC
+ * includes the expected necessary messages.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import java.util.LinkedList;
+
+public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
+  public static void main(String[] args) throws Exception {
+    testGCLogs();
+    testHumongousObjectGCLogs();
+  }
+
+  private static void testGCLogs() throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xms128M",
+                                               "-Xmx128M",
+                                               "-Xmn16M",
+                                               "-XX:G1HeapRegionSize=1M",
+                                               "-XX:+PrintGC",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
+                                               GCTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
+    // And GCTest doesn't have humongous objects, so values should be zero.
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldContain("[Humongous Total: 0]");
+    output.shouldContain("[Humongous Candidate: 0]");
+    output.shouldContain("[Humongous Reclaimed: 0]");
+
+    output.shouldHaveExitValue(0);
+  }
+
+  private static void testHumongousObjectGCLogs() throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                               "-Xms128M",
+                                               "-Xmx128M",
+                                               "-Xmn16M",
+                                               "-XX:G1HeapRegionSize=1M",
+                                               "-XX:+PrintGC",
+                                               "-XX:+UnlockExperimentalVMOptions",
+                                               "-XX:G1LogLevel=finest",
+                                               "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
+                                               GCWithHumongousObjectTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldContain("[Humongous Total");
+    output.shouldContain("[Humongous Candidate");
+    output.shouldContain("[Humongous Reclaimed");
+
+    // As G1TraceReclaimDeadHumongousObjectsAtYoungGC is set and GCWithHumongousObjectTest has humongous objects,
+    // these logs should be displayed.
+    output.shouldContain("Live humongous");
+    output.shouldContain("Reclaim humongous region");
+    output.shouldHaveExitValue(0);
+  }
+
+  static class GCTest {
+    private static byte[] garbage;
+
+    public static void main(String [] args) {
+      System.out.println("Creating garbage");
+      // create 128MB of garbage. This should result in at least one GC
+      for (int i = 0; i < 1024; i++) {
+        garbage = new byte[128 * 1024];
+      }
+      System.out.println("Done");
+    }
+  }
+
+  static class GCWithHumongousObjectTest {
+
+    public static final int M = 1024*1024;
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+    // A large object referenced by a static.
+    static int[] filler = new int[10 * M];
+
+    public static void genGarbage() {
+      for (int i = 0; i < 32*1024; i++) {
+        garbageList.add(new int[100]);
+      }
+      garbageList.clear();
+    }
+
+    public static void main(String[] args) {
+
+      int[] large = new int[M];
+      Object ref = large;
+
+      System.out.println("Creating garbage");
+      for (int i = 0; i < 100; i++) {
+        // A large object that will be reclaimed eagerly.
+        large = new int[6*M];
+        genGarbage();
+        // Make sure that the compiler cannot completely remove
+        // the allocation of the large object until here.
+        System.out.println(large);
+      }
+
+      // Keep the reference to the first object alive.
+      System.out.println(ref);
+      System.out.println("Done");
+    }
+  }
+}
--- a/test/gc/g1/TestGCLogMessages.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/gc/g1/TestGCLogMessages.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
  * 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,7 +23,7 @@
 
 /*
  * @test TestGCLogMessages
- * @bug 8035406 8027295 8035398 8019342 8027959
+ * @bug 8035406 8027295 8035398 8019342 8027959 8027962
  * @summary Ensure that the PrintGCDetails output for a minor GC with G1
  * includes the expected necessary messages.
  * @key gc
@@ -34,128 +34,158 @@
 import com.oracle.java.testlibrary.OutputAnalyzer;
 
 public class TestGCLogMessages {
-  public static void main(String[] args) throws Exception {
-    testNormalLogs();
-    testWithToSpaceExhaustionLogs();
-  }
 
-  private static void testNormalLogs() throws Exception {
-
-    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                                              "-Xmx10M",
-                                                              GCTest.class.getName());
+    private enum Level {
+        OFF, FINER, FINEST;
+        public boolean lessOrEqualTo(Level other) {
+            return this.compareTo(other) < 0;
+        }
+    }
 
-    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    private class LogMessageWithLevel {
+        String message;
+        Level level;
 
-    output.shouldNotContain("[Redirty Cards");
-    output.shouldNotContain("[Parallel Redirty");
-    output.shouldNotContain("[Redirtied Cards");
-    output.shouldNotContain("[Code Root Purge");
-    output.shouldNotContain("[String Dedup Fixup");
-    output.shouldNotContain("[Young Free CSet");
-    output.shouldNotContain("[Non-Young Free CSet");
-    output.shouldNotContain("[Humongous Reclaim");
-    output.shouldHaveExitValue(0);
+        public LogMessageWithLevel(String message, Level level) {
+            this.message = message;
+            this.level = level;
+        }
+    };
 
-    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-XX:+UseStringDeduplication",
-                                               "-Xmx10M",
-                                               "-XX:+PrintGCDetails",
-                                               GCTest.class.getName());
-
-    output = new OutputAnalyzer(pb.start());
+    private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] {
+        // Ext Root Scan
+        new LogMessageWithLevel("Thread Roots (ms)", Level.FINEST),
+        new LogMessageWithLevel("StringTable Roots (ms)", Level.FINEST),
+        new LogMessageWithLevel("Universe Roots (ms)", Level.FINEST),
+        new LogMessageWithLevel("JNI Handles Roots (ms)", Level.FINEST),
+        new LogMessageWithLevel("ObjectSynchronizer Roots (ms)", Level.FINEST),
+        new LogMessageWithLevel("FlatProfiler Roots", Level.FINEST),
+        new LogMessageWithLevel("Management Roots", Level.FINEST),
+        new LogMessageWithLevel("SystemDictionary Roots", Level.FINEST),
+        new LogMessageWithLevel("CLDG Roots", Level.FINEST),
+        new LogMessageWithLevel("JVMTI Roots", Level.FINEST),
+        new LogMessageWithLevel("CodeCache Roots", Level.FINEST),
+        new LogMessageWithLevel("SATB Filtering", Level.FINEST),
+        new LogMessageWithLevel("CM RefProcessor Roots", Level.FINEST),
+        new LogMessageWithLevel("Wait For Strong CLD", Level.FINEST),
+        new LogMessageWithLevel("Weak CLD Roots", Level.FINEST),
+        // Redirty Cards
+        new LogMessageWithLevel("Redirty Cards", Level.FINER),
+        new LogMessageWithLevel("Parallel Redirty", Level.FINEST),
+        new LogMessageWithLevel("Redirtied Cards", Level.FINEST),
+        // Misc Top-level
+        new LogMessageWithLevel("Code Root Purge", Level.FINER),
+        new LogMessageWithLevel("String Dedup Fixup", Level.FINER),
+        // Free CSet
+        new LogMessageWithLevel("Young Free CSet", Level.FINEST),
+        new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST),
+        // Humongous Eager Reclaim
+        new LogMessageWithLevel("Humongous Reclaim", Level.FINER),
+    };
 
-    output.shouldContain("[Redirty Cards");
-    output.shouldNotContain("[Parallel Redirty");
-    output.shouldNotContain("[Redirtied Cards");
-    output.shouldContain("[Code Root Purge");
-    output.shouldContain("[String Dedup Fixup");
-    output.shouldNotContain("[Young Free CSet");
-    output.shouldNotContain("[Non-Young Free CSet");
-    output.shouldContain("[Humongous Reclaim");
-    output.shouldNotContain("[Humongous Total");
-    output.shouldNotContain("[Humongous Candidate");
-    output.shouldNotContain("[Humongous Reclaimed");
-    output.shouldHaveExitValue(0);
+    void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception {
+        for (LogMessageWithLevel l : messages) {
+            if (level.lessOrEqualTo(l.level)) {
+                output.shouldNotContain(l.message);
+            } else {
+                output.shouldContain(l.message);
+            }
+        }
+    }
 
-    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-XX:+UseStringDeduplication",
-                                               "-Xmx10M",
-                                               "-XX:+PrintGCDetails",
-                                               "-XX:+UnlockExperimentalVMOptions",
-                                               "-XX:G1LogLevel=finest",
-                                               GCTest.class.getName());
+    public static void main(String[] args) throws Exception {
+        new TestGCLogMessages().testNormalLogs();
+        new TestGCLogMessages().testWithToSpaceExhaustionLogs();
+    }
+
+    private void testNormalLogs() throws Exception {
 
-    output = new OutputAnalyzer(pb.start());
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx10M",
+                                                                  GCTest.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.OFF);
+        output.shouldHaveExitValue(0);
 
-    output.shouldContain("[Redirty Cards");
-    output.shouldContain("[Parallel Redirty");
-    output.shouldContain("[Redirtied Cards");
-    output.shouldContain("[Code Root Purge");
-    output.shouldContain("[String Dedup Fixup");
-    output.shouldContain("[Young Free CSet");
-    output.shouldContain("[Non-Young Free CSet");
-    output.shouldContain("[Humongous Reclaim");
-    output.shouldContain("[Humongous Total");
-    output.shouldContain("[Humongous Candidate");
-    output.shouldContain("[Humongous Reclaimed");
-    output.shouldHaveExitValue(0);
-  }
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-XX:+UseStringDeduplication",
+                                                   "-Xmx10M",
+                                                   "-XX:+PrintGCDetails",
+                                                   GCTest.class.getName());
+
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.FINER);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-XX:+UseStringDeduplication",
+                                                   "-Xmx10M",
+                                                   "-XX:+PrintGCDetails",
+                                                   "-XX:+UnlockExperimentalVMOptions",
+                                                   "-XX:G1LogLevel=finest",
+                                                   GCTest.class.getName());
 
-  private static void testWithToSpaceExhaustionLogs() throws Exception {
-    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-Xmx10M",
-                                               "-Xmn5M",
-                                               "-XX:+PrintGCDetails",
-                                               GCTestWithToSpaceExhaustion.class.getName());
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.FINEST);
+        output.shouldHaveExitValue(0);
+    }
 
-    OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("[Evacuation Failure");
-    output.shouldNotContain("[Recalculate Used");
-    output.shouldNotContain("[Remove Self Forwards");
-    output.shouldNotContain("[Restore RemSet");
-    output.shouldHaveExitValue(0);
+    LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] {
+        new LogMessageWithLevel("Evacuation Failure", Level.FINER),
+        new LogMessageWithLevel("Recalculate Used", Level.FINEST),
+        new LogMessageWithLevel("Remove Self Forwards", Level.FINEST),
+        new LogMessageWithLevel("Restore RemSet", Level.FINEST),
+    };
 
-    pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
-                                               "-Xmx10M",
-                                               "-Xmn5M",
-                                               "-XX:+PrintGCDetails",
-                                               "-XX:+UnlockExperimentalVMOptions",
-                                               "-XX:G1LogLevel=finest",
-                                               GCTestWithToSpaceExhaustion.class.getName());
+    private void testWithToSpaceExhaustionLogs() throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx32M",
+                                                                  "-Xmn16M",
+                                                                  "-XX:+PrintGCDetails",
+                                                                  GCTestWithToSpaceExhaustion.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, exhFailureMessages, Level.FINER);
+        output.shouldHaveExitValue(0);
 
-    output = new OutputAnalyzer(pb.start());
-    output.shouldContain("[Evacuation Failure");
-    output.shouldContain("[Recalculate Used");
-    output.shouldContain("[Remove Self Forwards");
-    output.shouldContain("[Restore RemSet");
-    output.shouldHaveExitValue(0);
-  }
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-Xmx32M",
+                                                   "-Xmn16M",
+                                                   "-XX:+PrintGCDetails",
+                                                   "-XX:+UnlockExperimentalVMOptions",
+                                                   "-XX:G1LogLevel=finest",
+                                                   GCTestWithToSpaceExhaustion.class.getName());
 
-  static class GCTest {
-    private static byte[] garbage;
-    public static void main(String [] args) {
-      System.out.println("Creating garbage");
-      // create 128MB of garbage. This should result in at least one GC
-      for (int i = 0; i < 1024; i++) {
-        garbage = new byte[128 * 1024];
-      }
-      System.out.println("Done");
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, exhFailureMessages, Level.FINEST);
+        output.shouldHaveExitValue(0);
     }
-  }
+
+    static class GCTest {
+        private static byte[] garbage;
+        public static void main(String [] args) {
+            System.out.println("Creating garbage");
+            // create 128MB of garbage. This should result in at least one GC
+            for (int i = 0; i < 1024; i++) {
+                garbage = new byte[128 * 1024];
+            }
+            System.out.println("Done");
+        }
+    }
 
-  static class GCTestWithToSpaceExhaustion {
-    private static byte[] garbage;
-    private static byte[] largeObject;
-    public static void main(String [] args) {
-      largeObject = new byte[5*1024*1024];
-      System.out.println("Creating garbage");
-      // create 128MB of garbage. This should result in at least one GC,
-      // some of them with to-space exhaustion.
-      for (int i = 0; i < 1024; i++) {
-        garbage = new byte[128 * 1024];
-      }
-      System.out.println("Done");
+    static class GCTestWithToSpaceExhaustion {
+        private static byte[] garbage;
+        private static byte[] largeObject;
+        public static void main(String [] args) {
+            largeObject = new byte[16*1024*1024];
+            System.out.println("Creating garbage");
+            // create 128MB of garbage. This should result in at least one GC,
+            // some of them with to-space exhaustion.
+            for (int i = 0; i < 1024; i++) {
+                garbage = new byte[128 * 1024];
+            }
+            System.out.println("Done");
+        }
     }
-  }
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/AlignmentHelper.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.lang.management.MemoryPoolMXBean;
+import java.util.Optional;
+
+import sun.hotspot.WhiteBox;
+
+/**
+ * Helper class aimed to provide information about alignment of objects in
+ * particular heap space, expected memory usage after objects' allocation so on.
+ */
+public class AlignmentHelper {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    private static final long OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM = 8L;
+
+    /**
+     * Max relative allowed actual memory usage deviation from expected memory
+     * usage.
+     */
+    private static final float MAX_RELATIVE_DEVIATION = 0.05f; // 5%
+
+    public static final long OBJECT_ALIGNMENT_IN_BYTES = Optional.ofNullable(
+            AlignmentHelper.WHITE_BOX.getIntxVMFlag("ObjectAlignmentInBytes"))
+            .orElse(AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM);
+
+    public static final long SURVIVOR_ALIGNMENT_IN_BYTES = Optional.ofNullable(
+            AlignmentHelper.WHITE_BOX.getIntxVMFlag("SurvivorAlignmentInBytes"))
+            .orElseThrow(() ->new AssertionError(
+                    "Unable to get SurvivorAlignmentInBytes value"));
+    /**
+     * Min amount of memory that will be occupied by an object.
+     */
+    public static final long MIN_OBJECT_SIZE
+            = AlignmentHelper.WHITE_BOX.getObjectSize(new Object());
+    /**
+     * Min amount of memory that will be occupied by an empty byte array.
+     */
+    public static final long MIN_ARRAY_SIZE
+            = AlignmentHelper.WHITE_BOX.getObjectSize(new byte[0]);
+
+    /**
+     * Precision at which actual memory usage in a heap space represented by
+     * this sizing helper could be measured.
+     */
+    private final long memoryUsageMeasurementPrecision;
+    /**
+     * Min amount of memory that will be occupied by an object allocated in a
+     * heap space represented by this sizing helper.
+     */
+    private final long minObjectSizeInThisSpace;
+    /**
+     * Object's alignment in a heap space represented by this sizing helper.
+     */
+    private final long objectAlignmentInThisRegion;
+    /**
+     * MemoryPoolMXBean associated with a heap space represented by this sizing
+     * helper.
+     */
+    private final MemoryPoolMXBean poolMXBean;
+
+    private static long alignUp(long value, long alignment) {
+        return ((value - 1) / alignment + 1) * alignment;
+    }
+
+    protected AlignmentHelper(long memoryUsageMeasurementPrecision,
+            long objectAlignmentInThisRegion, long minObjectSizeInThisSpace,
+            MemoryPoolMXBean poolMXBean) {
+        this.memoryUsageMeasurementPrecision = memoryUsageMeasurementPrecision;
+        this.minObjectSizeInThisSpace = minObjectSizeInThisSpace;
+        this.objectAlignmentInThisRegion = objectAlignmentInThisRegion;
+        this.poolMXBean = poolMXBean;
+    }
+
+    /**
+     * Returns how many objects have to be allocated to fill
+     * {@code memoryToFill} bytes in this heap space using objects of size
+     * {@code objectSize}.
+     */
+    public int getObjectsCount(long memoryToFill, long objectSize) {
+        return (int) (memoryToFill / getObjectSizeInThisSpace(objectSize));
+    }
+
+    /**
+     * Returns amount of memory that {@code objectsCount} of objects with size
+     * {@code objectSize} will occupy this this space after allocation.
+     */
+    public long getExpectedMemoryUsage(long objectSize, int objectsCount) {
+        long correctedObjectSize = getObjectSizeInThisSpace(objectSize);
+        return AlignmentHelper.alignUp(correctedObjectSize * objectsCount,
+                memoryUsageMeasurementPrecision);
+    }
+
+    /**
+     * Returns current memory usage in this heap space.
+     */
+    public long getActualMemoryUsage() {
+        return poolMXBean.getUsage().getUsed();
+    }
+
+    /**
+     * Returns maximum memory usage deviation from {@code expectedMemoryUsage}
+     * given the max allowed relative deviation equal to
+     * {@code relativeDeviation}.
+     *
+     * Note that value returned by this method is aligned according to
+     * memory measurement precision for this heap space.
+     */
+    public long getAllowedMemoryUsageDeviation(long expectedMemoryUsage) {
+        long unalignedDeviation = (long) (expectedMemoryUsage *
+                AlignmentHelper.MAX_RELATIVE_DEVIATION);
+        return AlignmentHelper.alignUp(unalignedDeviation,
+                memoryUsageMeasurementPrecision);
+    }
+
+    /**
+     * Returns amount of memory that will be occupied by an object with size
+     * {@code objectSize} in this heap space.
+     */
+    public long getObjectSizeInThisSpace(long objectSize) {
+        objectSize = Math.max(objectSize, minObjectSizeInThisSpace);
+
+        long alignedObjectSize = AlignmentHelper.alignUp(objectSize,
+                objectAlignmentInThisRegion);
+        long sizeDiff = alignedObjectSize - objectSize;
+
+        // If there is not enough space to fit padding object, then object will
+        // be aligned to {@code 2 * objectAlignmentInThisRegion}.
+        if (sizeDiff >= AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES
+                && sizeDiff < AlignmentHelper.MIN_OBJECT_SIZE) {
+            alignedObjectSize += AlignmentHelper.MIN_OBJECT_SIZE;
+            alignedObjectSize = AlignmentHelper.alignUp(alignedObjectSize,
+                    objectAlignmentInThisRegion);
+        }
+
+        return alignedObjectSize;
+    }
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("AlignmentHelper for memory pool '%s':%n",
+                poolMXBean.getName()));
+        builder.append(String.format("Memory usage measurement precision: %d%n",
+                memoryUsageMeasurementPrecision));
+        builder.append(String.format("Min object size in this space: %d%n",
+                minObjectSizeInThisSpace));
+        builder.append(String.format("Object alignment in this space: %d%n",
+                objectAlignmentInThisRegion));
+
+        return builder.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/SurvivorAlignmentTestMain.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.sun.management.ThreadMXBean;
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+
+/**
+ * Main class for tests on {@code SurvivorAlignmentInBytes} option.
+ *
+ * Typical usage is to obtain instance using fromArgs method, allocate objects
+ * and verify that actual memory usage in tested heap space is close to
+ * expected.
+ */
+public class SurvivorAlignmentTestMain {
+    enum HeapSpace {
+        EDEN,
+        SURVIVOR,
+        TENURED
+    }
+
+    public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    public static final long MAX_TENURING_THRESHOLD = Optional.ofNullable(
+            SurvivorAlignmentTestMain.WHITE_BOX.getIntxVMFlag(
+                    "MaxTenuringThreshold")).orElse(15L);
+
+    /**
+     * Regexp used to parse memory size params, like 2G, 34m or 15k.
+     */
+    private static final Pattern SIZE_REGEX
+            = Pattern.compile("(?<size>[0-9]+)(?<multiplier>[GMKgmk])?");
+
+    // Names of different heap spaces.
+    private static final String DEF_NEW_EDEN = "Eden Space";
+    private static final String DEF_NEW_SURVIVOR = "Survivor Space";
+    private static final String PAR_NEW_EDEN = "Par Eden Space";
+    private static final String PAR_NEW_SURVIVOR = "Par Survivor Space";
+    private static final String PS_EDEN = "PS Eden Space";
+    private static final String PS_SURVIVOR = "PS Survivor Space";
+    private static final String G1_EDEN = "G1 Eden Space";
+    private static final String G1_SURVIVOR = "G1 Survivor Space";
+    private static final String SERIAL_TENURED = "Tenured Gen";
+    private static final String CMS_TENURED = "CMS Old Gen";
+    private static final String PS_TENURED = "PS Old Gen";
+    private static final String G1_TENURED = "G1 Old Gen";
+
+    private static final long G1_HEAP_REGION_SIZE = Optional.ofNullable(
+            SurvivorAlignmentTestMain.WHITE_BOX.getUintxVMFlag(
+                    "G1HeapRegionSize")).orElse(-1L);
+
+    /**
+     * Min size of free chunk in CMS generation.
+     * An object allocated in CMS generation will at least occupy this amount
+     * of bytes.
+     */
+    private static final long CMS_MIN_FREE_CHUNK_SIZE
+            = 3L * Unsafe.ADDRESS_SIZE;
+
+    private static final AlignmentHelper EDEN_SPACE_HELPER;
+    private static final AlignmentHelper SURVIVOR_SPACE_HELPER;
+    private static final AlignmentHelper TENURED_SPACE_HELPER;
+    /**
+     * Amount of memory that should be filled during a test run.
+     */
+    private final long memoryToFill;
+    /**
+     * The size of an objects that will be allocated during a test run.
+     */
+    private final long objectSize;
+    /**
+     * Amount of memory that will be actually occupied by an object in eden
+     * space.
+     */
+    private final long actualObjectSize;
+    /**
+     * Storage for allocated objects.
+     */
+    private final Object[] garbage;
+    /**
+     * Heap space whose memory usage is a subject of assertions during the test
+     * run.
+     */
+    private final HeapSpace testedSpace;
+
+    private long[] baselinedThreadMemoryUsage = null;
+    private long[] threadIds = null;
+
+    /**
+     * Initialize {@code EDEN_SPACE_HELPER}, {@code SURVIVOR_SPACE_HELPER} and
+     * {@code TENURED_SPACE_HELPER} to represent heap spaces in use.
+     *
+     * Note that regardless to GC object's alignment in survivor space is
+     * expected to be equal to {@code SurvivorAlignmentInBytes} value and
+     * alignment in other spaces is expected to be equal to
+     * {@code ObjectAlignmentInBytes} value.
+     *
+     * In CMS generation we can't allocate less then {@code MinFreeChunk} value,
+     * for other CGs we expect that object of size {@code MIN_OBJECT_SIZE}
+     * could be allocated as it is (of course, its size could be aligned
+     * according to alignment value used in a particular space).
+     *
+     * For G1 GC MXBeans could report memory usage only with region size
+     * precision (if an object allocated in some G1 heap region, then all region
+     * will claimed as used), so for G1's spaces precision is equal to
+     * {@code G1HeapRegionSize} value.
+     */
+    static {
+        AlignmentHelper edenHelper = null;
+        AlignmentHelper survivorHelper = null;
+        AlignmentHelper tenuredHelper = null;
+        for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
+            switch (pool.getName()) {
+                case SurvivorAlignmentTestMain.DEF_NEW_EDEN:
+                case SurvivorAlignmentTestMain.PAR_NEW_EDEN:
+                case SurvivorAlignmentTestMain.PS_EDEN:
+                    Asserts.assertNull(edenHelper,
+                            "Only one bean for eden space is expected.");
+                    edenHelper = new AlignmentHelper(
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.MIN_OBJECT_SIZE, pool);
+                    break;
+                case SurvivorAlignmentTestMain.G1_EDEN:
+                    Asserts.assertNull(edenHelper,
+                            "Only one bean for eden space is expected.");
+                    edenHelper = new AlignmentHelper(
+                            SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE,
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.MIN_OBJECT_SIZE, pool);
+                    break;
+                case SurvivorAlignmentTestMain.DEF_NEW_SURVIVOR:
+                case SurvivorAlignmentTestMain.PAR_NEW_SURVIVOR:
+                case SurvivorAlignmentTestMain.PS_SURVIVOR:
+                    Asserts.assertNull(survivorHelper,
+                            "Only one bean for survivor space is expected.");
+                    survivorHelper = new AlignmentHelper(
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.MIN_OBJECT_SIZE, pool);
+                    break;
+                case SurvivorAlignmentTestMain.G1_SURVIVOR:
+                    Asserts.assertNull(survivorHelper,
+                            "Only one bean for survivor space is expected.");
+                    survivorHelper = new AlignmentHelper(
+                            SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE,
+                            AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.MIN_OBJECT_SIZE, pool);
+                    break;
+                case SurvivorAlignmentTestMain.SERIAL_TENURED:
+                case SurvivorAlignmentTestMain.PS_TENURED:
+                case SurvivorAlignmentTestMain.G1_TENURED:
+                    Asserts.assertNull(tenuredHelper,
+                            "Only one bean for tenured space is expected.");
+                    tenuredHelper = new AlignmentHelper(
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.MIN_OBJECT_SIZE, pool);
+                    break;
+                case SurvivorAlignmentTestMain.CMS_TENURED:
+                    Asserts.assertNull(tenuredHelper,
+                            "Only one bean for tenured space is expected.");
+                    tenuredHelper = new AlignmentHelper(
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES,
+                            SurvivorAlignmentTestMain.CMS_MIN_FREE_CHUNK_SIZE,
+                            pool);
+                    break;
+            }
+        }
+        EDEN_SPACE_HELPER = Objects.requireNonNull(edenHelper,
+                "AlignmentHelper for eden space should be initialized.");
+        SURVIVOR_SPACE_HELPER = Objects.requireNonNull(survivorHelper,
+                "AlignmentHelper for survivor space should be initialized.");
+        TENURED_SPACE_HELPER = Objects.requireNonNull(tenuredHelper,
+                "AlignmentHelper for tenured space should be initialized.");
+    }
+    /**
+     * Returns an SurvivorAlignmentTestMain instance constructed using CLI
+     * options.
+     *
+     * Following options are expected:
+     * <ul>
+     *     <li>memoryToFill</li>
+     *     <li>objectSize</li>
+     * </ul>
+     *
+     * Both argument may contain multiplier suffix k, m or g.
+     */
+    public static SurvivorAlignmentTestMain fromArgs(String[] args) {
+        Asserts.assertEQ(args.length, 3, "Expected three arguments: "
+                + "memory size, object size and tested heap space name.");
+
+        long memoryToFill = parseSize(args[0]);
+        long objectSize = Math.max(parseSize(args[1]),
+                AlignmentHelper.MIN_ARRAY_SIZE);
+        HeapSpace testedSpace = HeapSpace.valueOf(args[2]);
+
+        return new SurvivorAlignmentTestMain(memoryToFill, objectSize,
+                testedSpace);
+    }
+
+    /**
+     * Returns a value parsed from a string with format
+     * &lt;integer&gt;&lt;multiplier&gt;.
+     */
+    private static long parseSize(String sizeString) {
+        Matcher matcher = SIZE_REGEX.matcher(sizeString);
+        Asserts.assertTrue(matcher.matches(),
+                "sizeString should have following format \"[0-9]+([MBK])?\"");
+        long size = Long.valueOf(matcher.group("size"));
+
+        if (matcher.group("multiplier") != null) {
+            long K = 1024L;
+            // fall through multipliers
+            switch (matcher.group("multiplier").toLowerCase()) {
+                case "g":
+                    size *= K;
+                case "m":
+                    size *= K;
+                case "k":
+                    size *= K;
+            }
+        }
+        return size;
+    }
+
+    private SurvivorAlignmentTestMain(long memoryToFill, long objectSize,
+            HeapSpace testedSpace) {
+        this.objectSize = objectSize;
+        this.memoryToFill = memoryToFill;
+        this.testedSpace = testedSpace;
+
+        AlignmentHelper helper = SurvivorAlignmentTestMain.EDEN_SPACE_HELPER;
+
+        this.actualObjectSize = helper.getObjectSizeInThisSpace(
+                this.objectSize);
+        int arrayLength = helper.getObjectsCount(memoryToFill, this.objectSize);
+        garbage = new Object[arrayLength];
+    }
+
+    /**
+     * Allocate byte arrays to fill {@code memoryToFill} memory.
+     */
+    public void allocate() {
+        int byteArrayLength = Math.max((int) (objectSize
+                - Unsafe.ARRAY_BYTE_BASE_OFFSET), 0);
+
+        for (int i = 0; i < garbage.length; i++) {
+            garbage[i] = new byte[byteArrayLength];
+        }
+    }
+
+    /**
+     * Release memory occupied after {@code allocate} call.
+     */
+    public void release() {
+        for (int i = 0; i < garbage.length; i++) {
+            garbage[i] = null;
+        }
+    }
+
+    /**
+     * Returns expected amount of memory occupied in a {@code heapSpace} by
+     * objects referenced from {@code garbage} array.
+     */
+    public long getExpectedMemoryUsage() {
+        AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace);
+        return alignmentHelper.getExpectedMemoryUsage(objectSize,
+                garbage.length);
+    }
+
+    /**
+     * Verifies that memory usage in a {@code heapSpace} deviates from
+     * {@code expectedUsage} for no more than {@code MAX_RELATIVE_DEVIATION}.
+     */
+    public void verifyMemoryUsage(long expectedUsage) {
+        AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace);
+
+        long actualMemoryUsage = alignmentHelper.getActualMemoryUsage();
+        boolean otherThreadsAllocatedMemory = areOtherThreadsAllocatedMemory();
+
+        long memoryUsageDiff = Math.abs(actualMemoryUsage - expectedUsage);
+        long maxAllowedUsageDiff
+                = alignmentHelper.getAllowedMemoryUsageDeviation(expectedUsage);
+
+        System.out.println("Verifying memory usage in space: " + testedSpace);
+        System.out.println("Allocated objects count: " + garbage.length);
+        System.out.println("Desired object size: " + objectSize);
+        System.out.println("Actual object size: " + actualObjectSize);
+        System.out.println("Expected object size in space: "
+                + alignmentHelper.getObjectSizeInThisSpace(objectSize));
+        System.out.println("Expected memory usage: " + expectedUsage);
+        System.out.println("Actual memory usage: " + actualMemoryUsage);
+        System.out.println("Memory usage diff: " + memoryUsageDiff);
+        System.out.println("Max allowed usage diff: " + maxAllowedUsageDiff);
+
+        if (memoryUsageDiff > maxAllowedUsageDiff
+                && otherThreadsAllocatedMemory) {
+            System.out.println("Memory usage diff is incorrect, but it seems "
+                    + "like someone else allocated objects");
+            return;
+        }
+
+        Asserts.assertLTE(memoryUsageDiff, maxAllowedUsageDiff,
+                "Actual memory usage should not deviate from expected for " +
+                        "more then " + maxAllowedUsageDiff);
+    }
+
+    /**
+     * Baselines amount of memory allocated by each thread.
+     */
+    public void baselineMemoryAllocation() {
+        ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
+        threadIds = bean.getAllThreadIds();
+        baselinedThreadMemoryUsage = bean.getThreadAllocatedBytes(threadIds);
+    }
+
+    /**
+     * Checks if threads other then the current thread were allocating objects
+     * after baselinedThreadMemoryUsage call.
+     *
+     * If baselinedThreadMemoryUsage was not called, then this method will return
+     * {@code false}.
+     */
+    public boolean areOtherThreadsAllocatedMemory() {
+        if (baselinedThreadMemoryUsage == null) {
+            return false;
+        }
+
+        ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
+        long currentMemoryAllocation[]
+                = bean.getThreadAllocatedBytes(threadIds);
+        boolean otherThreadsAllocatedMemory = false;
+
+        System.out.println("Verifying amount of memory allocated by threads:");
+        for (int i = 0; i < threadIds.length; i++) {
+            System.out.format("Thread %d%nbaseline allocation: %d"
+                            + "%ncurrent allocation:%d%n", threadIds[i],
+                    baselinedThreadMemoryUsage[i], currentMemoryAllocation[i]);
+            System.out.println(bean.getThreadInfo(threadIds[i]));
+
+            long bytesAllocated = Math.abs(currentMemoryAllocation[i]
+                    - baselinedThreadMemoryUsage[i]);
+            if (bytesAllocated > 0
+                    && threadIds[i] != Thread.currentThread().getId()) {
+                otherThreadsAllocatedMemory = true;
+            }
+        }
+
+        return otherThreadsAllocatedMemory;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("SurvivorAlignmentTestMain info:%n"));
+        builder.append(String.format("Desired object size: %d%n", objectSize));
+        builder.append(String.format("Memory to fill: %d%n", memoryToFill));
+        builder.append(String.format("Objects to be allocated: %d%n",
+                garbage.length));
+
+        builder.append(String.format("Alignment helpers to be used: %n"));
+        for (HeapSpace heapSpace: HeapSpace.values()) {
+            builder.append(String.format("For space %s:%n%s%n", heapSpace,
+                    getAlignmentHelper(heapSpace)));
+        }
+
+        return builder.toString();
+    }
+
+    /**
+     * Returns {@code AlignmentHelper} for a space {@code heapSpace}.
+     */
+    public static AlignmentHelper getAlignmentHelper(HeapSpace heapSpace) {
+        switch (heapSpace) {
+            case EDEN:
+                return SurvivorAlignmentTestMain.EDEN_SPACE_HELPER;
+            case SURVIVOR:
+                return SurvivorAlignmentTestMain.SURVIVOR_SPACE_HELPER;
+            case TENURED:
+                return SurvivorAlignmentTestMain.TENURED_SPACE_HELPER;
+            default:
+                throw new Error("Unexpected heap space: " + heapSpace);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/TestAllocationInEden.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8031323
+ * @summary Verify that object's alignment in eden space is not affected by
+ *          SurvivorAlignmentInBytes option.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestAllocationInEden SurvivorAlignmentTestMain AlignmentHelper
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB
+ *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 9 EDEN
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB
+ *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 47 EDEN
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB
+ *                   -XX:OldSize=128m  -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 9 EDEN
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB
+ *                   -XX:OldSize=128m  -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 87 EDEN
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB
+ *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 9 EDEN
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB
+ *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   TestAllocationInEden 10m 147 EDEN
+ */
+public class TestAllocationInEden {
+    public static void main(String args[]) {
+        SurvivorAlignmentTestMain test
+                = SurvivorAlignmentTestMain.fromArgs(args);
+        System.out.println(test);
+
+        long expectedMemoryUsage = test.getExpectedMemoryUsage();
+        test.baselineMemoryAllocation();
+        System.gc();
+
+        test.allocate();
+
+        test.verifyMemoryUsage(expectedMemoryUsage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8031323
+ * @summary Verify that objects promoted from eden space to tenured space during
+ *          full GC are not aligned to SurvivorAlignmentInBytes value.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestPromotionFromEdenToTenured SurvivorAlignmentTestMain
+ *        AlignmentHelper
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromEdenToTenured 10m 9 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromEdenToTenured 10m 47 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32m  -XX:MaxHeapSize=96m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromEdenToTenured 10m 9 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromEdenToTenured 10m 87 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                   TestPromotionFromEdenToTenured 10m 9 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                   TestPromotionFromEdenToTenured 10m 147 TENURED
+ */
+public class TestPromotionFromEdenToTenured {
+    public static void main(String args[]) {
+        SurvivorAlignmentTestMain test
+                = SurvivorAlignmentTestMain.fromArgs(args);
+        System.out.println(test);
+
+        long expectedMemoryUsage = test.getExpectedMemoryUsage();
+        test.baselineMemoryAllocation();
+        System.gc();
+        // increase expected usage by current old gen usage
+        expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper(
+                SurvivorAlignmentTestMain.HeapSpace.TENURED)
+                .getActualMemoryUsage();
+
+        test.allocate();
+        System.gc();
+
+        test.verifyMemoryUsage(expectedMemoryUsage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8031323
+ * @summary Verify that objects promoted from survivor space to tenured space
+ *          during full GC are not aligned to SurvivorAlignmentInBytes value.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestPromotionFromSurvivorToTenuredAfterFullGC
+ *        SurvivorAlignmentTestMain AlignmentHelper
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromSurvivorToTenuredAfterFullGC 20m 47
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=232m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromSurvivorToTenuredAfterFullGC 20m 87
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=288m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                    TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9
+ *                    TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                   TestPromotionFromSurvivorToTenuredAfterFullGC 20m 147
+ *                   TENURED
+ */
+public class TestPromotionFromSurvivorToTenuredAfterFullGC {
+    public static void main(String args[]) {
+        SurvivorAlignmentTestMain test
+                = SurvivorAlignmentTestMain.fromArgs(args);
+        System.out.println(test);
+
+        long expectedMemoryUsage = test.getExpectedMemoryUsage();
+        test.baselineMemoryAllocation();
+        System.gc();
+        // increase expected usage by current old gen usage
+        expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper(
+                SurvivorAlignmentTestMain.HeapSpace.TENURED)
+                .getActualMemoryUsage();
+
+        test.allocate();
+        SurvivorAlignmentTestMain.WHITE_BOX.youngGC();
+        System.gc();
+
+        test.verifyMemoryUsage(expectedMemoryUsage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8031323
+ * @summary Verify that objects promoted from survivor space to tenured space
+ *          when their age exceeded tenuring threshold are not aligned to
+ *          SurvivorAlignmentInBytes value.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestPromotionFromSurvivorToTenuredAfterMinorGC
+ *        SurvivorAlignmentTestMain AlignmentHelper
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32
+ *                   TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 47
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64
+ *                   TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 87
+ *                   TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                    TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9
+ *                    TENURED
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128
+ *                   TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 147
+ *                   TENURED
+ */
+public class TestPromotionFromSurvivorToTenuredAfterMinorGC {
+    public static void main(String args[]) throws Exception {
+        SurvivorAlignmentTestMain test
+                = SurvivorAlignmentTestMain.fromArgs(args);
+        System.out.println(test);
+
+        long expectedMemoryUsage = test.getExpectedMemoryUsage();
+        test.baselineMemoryAllocation();
+        SurvivorAlignmentTestMain.WHITE_BOX.fullGC();
+        // increase expected usage by current old gen usage
+        expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper(
+                SurvivorAlignmentTestMain.HeapSpace.TENURED)
+                .getActualMemoryUsage();
+
+        test.allocate();
+        for (int i = 0; i <= SurvivorAlignmentTestMain.MAX_TENURING_THRESHOLD;
+             i++) {
+            SurvivorAlignmentTestMain.WHITE_BOX.youngGC();
+        }
+
+        test.verifyMemoryUsage(expectedMemoryUsage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/TestPromotionToSurvivor.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8031323
+ * @summary Verify that objects promoted from eden space to survivor space after
+ *          minor GC are aligned to SurvivorAlignmentInBytes.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestPromotionToSurvivor
+ *        SurvivorAlignmentTestMain AlignmentHelper
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 10m 9 SURVIVOR
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 20m 47 SURVIVOR
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 8m 9 SURVIVOR
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 20m 87 SURVIVOR
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=384m  -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 10m 9 SURVIVOR
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
+ *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   TestPromotionToSurvivor 20m 147 SURVIVOR
+ */
+public class TestPromotionToSurvivor {
+    public static void main(String args[]) {
+        SurvivorAlignmentTestMain test
+                = SurvivorAlignmentTestMain.fromArgs(args);
+        System.out.println(test);
+
+        long expectedUsage = test.getExpectedMemoryUsage();
+        test.baselineMemoryAllocation();
+        SurvivorAlignmentTestMain.WHITE_BOX.fullGC();
+
+        test.allocate();
+        SurvivorAlignmentTestMain.WHITE_BOX.youngGC();
+
+        test.verifyMemoryUsage(expectedUsage);
+    }
+}
--- a/test/runtime/6888954/vmerrors.sh	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/runtime/6888954/vmerrors.sh	Wed Apr 22 06:24:15 2015 +0100
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -61,11 +61,12 @@
 # EXCEPTION_ACCESS_VIOLATION - Win-*
 # SIGBUS - Solaris SPARC-64
 # SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-*
+# SIGILL - Aix
 #
 # Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-*
 # gets its signal at a PC in test_error_handler().
 #
-bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
+bad_func_ptr_re='(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc='
 guarantee_re='guarantee[(](str|num).*failed: *'
 fatal_re='fatal error: *'
 tail_1='.*expected null'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/handlerInTry/HandlerInTry.jasm	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * HandlerInTry contains a try block in a ctor whose handler is inside
+ * the same try block.  The try block starts at line 74 (try t2;), ends at
+ * line 106 (endtry t2;), but its handler starts at line 101 (catch t2 #0;).
+ */
+super public class HandlerInTry
+    version 51:0
+{
+
+public static final synthetic Field ___transactionFactory_2002349702336125:"Ljava/lang/Object;";
+
+public Method "<init>":"(Ljava/lang/Object;)V"
+    stack 5 locals 5
+{
+        invokestatic    Method ThreadLocalTransaction.getThreadLocalTransaction:"()Ljava/lang/Object;";
+        checkcast    class java/lang/Object;
+        astore_2;
+        aload_2;
+        invokestatic    Method TransactionLogicDonor.isActiveTransaction:"(Ljava/lang/Object;)Z";
+        ifeq    L21;
+        aload_0;
+        aload_1;
+        aload_2;
+        invokespecial    Method "<init>":"(Ljava/lang/Object;Ljava/lang/Object;)V";
+        return;
+    L21:    stack_frame_type append;
+        locals_map class java/lang/Object;
+        aload_2;
+        getstatic    Field ___transactionFactory_2002349702336125:"Ljava/lang/Object;";
+        invokestatic    Method TransactionLogicDonor.createTransaction:"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;";
+        astore_2;
+        aload_2;
+        iconst_1;
+        pop;
+        aload_2;
+        invokestatic    Method ThreadLocalTransaction.setThreadLocalTransaction:"(Ljava/lang/Object;)V";
+        try t0, t1;
+        aload_0;
+        aload_1;
+        aload_2;
+        invokespecial    Method "<init>":"(Ljava/lang/Object;Ljava/lang/Object;)V";
+        aload_2;
+        pop;
+        aconst_null;
+        astore_2;
+        endtry t0, t1;
+        invokestatic    Method ThreadLocalTransaction.clearThreadLocalTransaction:"()V";
+        pop;
+        goto    L107;
+        catch t0 java/lang/Throwable;
+        try t2;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore_3;
+        aload_2;
+        pop;
+        aload_3;
+        instanceof    class ControlFlowError;
+        ifeq    L82;
+        new    class java/lang/NullPointerException;
+        dup;
+        invokespecial    Method java/lang/NullPointerException."<init>":"()V";
+        athrow;
+    L82:    stack_frame_type append;
+        locals_map class java/lang/Throwable;
+        aload_3;
+        instanceof    class java/lang/Error;
+        ifeq    L94;
+        aload_3;
+        checkcast    class java/lang/Error;
+        athrow;
+    L94:    stack_frame_type same;
+        aload_3;
+        checkcast    class java/lang/Exception;
+        athrow;
+        catch t1 #0;
+        catch t2 #0;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore    4;
+        endtry t2;
+        invokestatic    Method ThreadLocalTransaction.clearThreadLocalTransaction:"()V";
+        aload    4;
+        athrow;
+    L107:    stack_frame_type full;
+        locals_map class HandlerInTry, class java/lang/Object, null;
+        return;
+}
+
+} // end Class HandlerInTry
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/handlerInTry/IsolatedHandlerInTry.jasm	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * IsolatedHandlerInTry contains a try block in a ctor whose handler is inside
+ * the same try block but the handler can only be reached if an exception
+ * occurs.  The handler does a return.  So, a VerifyException should be thrown.
+ * The try block starts at line 77 (try t2;) and ends at line 113 (endtry t2;).
+ * Its handler starts at line 107 (catch t2 #0;).  The handler can only be reached
+ * by exception because of the athrow at line 106.
+ */
+super public class IsolatedHandlerInTry
+    version 51:0
+{
+
+public static final synthetic Field ___transactionFactory_2002349702336125:"Ljava/lang/Object;";
+
+public Method "<init>":"(Ljava/lang/Object;)V"
+    stack 5 locals 5
+{
+        invokestatic    Method ThreadLocalTransaction.getThreadLocalTransaction:"()Ljava/lang/Object;";
+        checkcast    class java/lang/Object;
+        astore_2;
+        aload_2;
+        invokestatic    Method TransactionLogicDonor.isActiveTransaction:"(Ljava/lang/Object;)Z";
+        ifeq    L21;
+        aload_0;
+        aload_1;
+        aload_2;
+        invokespecial    Method "<init>":"(Ljava/lang/Object;Ljava/lang/Object;)V";
+        return;
+    L21:    stack_frame_type append;
+        locals_map class java/lang/Object;
+        aload_2;
+        getstatic    Field ___transactionFactory_2002349702336125:"Ljava/lang/Object;";
+        invokestatic    Method TransactionLogicDonor.createTransaction:"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;";
+        astore_2;
+        aload_2;
+        iconst_1;
+        pop;
+        aload_2;
+        invokestatic    Method ThreadLocalTransaction.setThreadLocalTransaction:"(Ljava/lang/Object;)V";
+        try t0, t1;
+        aload_0;
+        aload_1;
+        aload_2;
+        invokespecial    Method "<init>":"(Ljava/lang/Object;Ljava/lang/Object;)V";
+        aload_2;
+        pop;
+        aconst_null;
+        astore_2;
+        endtry t0, t1;
+        invokestatic    Method ThreadLocalTransaction.clearThreadLocalTransaction:"()V";
+        pop;
+        goto    L107;
+        catch t0 java/lang/Throwable;
+        try t2;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore_3;
+        aload_2;
+        pop;
+        aload_3;
+        instanceof    class ControlFlowError;
+        ifeq    L82;
+        new    class java/lang/NullPointerException;
+        dup;
+        invokespecial    Method java/lang/NullPointerException."<init>":"()V";
+        athrow;
+    L82:    stack_frame_type append;
+        locals_map class java/lang/Throwable;
+        aload_3;
+        instanceof    class java/lang/Error;
+        ifeq    L94;
+        aload_3;
+        checkcast    class java/lang/Error;
+        athrow;
+    L94:    stack_frame_type same;
+        aload_3;
+        checkcast    class java/lang/Exception;
+        catch t1 #0;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        athrow;
+        catch t2 #0;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore    4;
+        return;
+        endtry t2;
+        stack_frame_type full;
+        locals_map bogus, class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        invokestatic    Method ThreadLocalTransaction.clearThreadLocalTransaction:"()V";
+        athrow;
+    L107:    stack_frame_type full;
+        locals_map class IsolatedHandlerInTry, class java/lang/Object, null;
+        return;
+}
+
+} // end Class IsolatedHandlerInTry
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/handlerInTry/LoadHandlerInTry.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8075118
+ * @summary Allow a ctor to call super() from a switch bytecode.
+ * @compile HandlerInTry.jasm
+ * @compile IsolatedHandlerInTry.jasm
+ * @run main/othervm -Xverify:all LoadHandlerInTry
+ */
+
+/*
+ * This test has two cases:
+ *
+ * 1. class HandlerInTry:  Class HandlerInTry contains a TRY block in a
+ *    constructor whose handler is inside the same TRY block.  The last
+ *    few bytecodes and exception table look like this:
+ *
+ *         ...
+ *      87: athrow
+ *      88: astore        4
+ *      90: invokestatic  #9
+ *      93: aload         4
+ *      95: athrow
+ *      96: return
+ *    Exception table:
+ *       from    to  target type
+ *          36    46    53   Class java/lang/Throwable
+ *          36    46    88   any
+ *          53    90    88   any
+ *
+ * Note that the target for the third handler in the Exception table is
+ * inside its TRY block.
+ * Without the fix for bug JDK-8075118, this test will time out.
+ *
+ *
+ * 2. class IsolatedHandlerInTry: Class IsolatedHandlerInTry also contains
+ *    a TRY block in a constructoer whose handler is inside its TRY block.
+ *    But the handler is only reachable if an exception is thrown.  The
+ *    handler's bytecodes will not get parsed as part of parsing the TRY
+ *    block.  They will only get parsed as a handler for the TRY block.
+ *    Since the isolated handler does a 'return', a VerifyError exception
+ *    should get thrown.
+ */
+
+public class LoadHandlerInTry {
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Regression test for bug 8075118");
+        try {
+            Class newClass = Class.forName("HandlerInTry");
+        } catch (Exception e) {
+            System.out.println("Failed: Exception was thrown: " + e.toString());
+            throw e;
+        }
+
+        try {
+            Class newClass = Class.forName("IsolatedHandlerInTry");
+            throw new RuntimeException(
+                 "Failed to throw VerifyError for IsolatedHandlerInTry");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("Passed: VerifyError exception was thrown");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/stackMapCheck/BadMap.jasm	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,152 @@
+ /*
+  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please 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 class should throw VerifyError because the StackMap for bytecode index
+ * 45 (astore_2, line 123) is incorrect. The stack maps for bytecode indexes 45
+ * and 49 (astore, line 133) do not match because 45 does not supply enough
+ * locals to satisfy 49.
+ *
+ * The astore_2 bytecode at bytecode index 45 changes the type state,
+ * preventing the stackmap mismatch.  But, if the incoming type state is used,
+ * as required by JVM Spec 8, then the verifier will detected the stackmap
+ * mismatch, and throw VerifyError.
+ */
+
+super public class BadMap
+    version 51:0
+{
+
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+        aload_0;
+        invokespecial    Method java/lang/Object."<init>":"()V";
+        return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+    throws java/lang/Throwable
+    stack 0 locals 1
+{
+        return;
+}
+
+public static Method foo:"()V"
+    stack 3 locals 5
+{
+        iconst_0;
+        ifne    L5;
+        nop;
+        try t7;
+    L5:    stack_frame_type full;
+        aconst_null;
+        dup;
+        astore_0;
+        astore_1;
+        try t0;
+        aconst_null;
+        astore_0;
+        endtry t0;
+        goto    L19;
+        catch t0 java/io/IOException;
+        stack_frame_type full;
+        locals_map class java/lang/Object, null;
+        stack_map class java/io/IOException;
+        astore_2;
+        aconst_null;
+        dup;
+        astore_1;
+        astore_0;
+        try t1;
+    L19:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object;
+        aconst_null;
+        astore_2;
+        endtry t1;
+        aload_1;
+        ifnonnull    L37;
+        nop;
+        goto    L37;
+        catch t1 #0;
+        catch t2 #0;
+        try t2;
+        stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore_3;
+        endtry t2;
+        aload_1;
+        ifnonnull    L35;
+        nop;
+    L35:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, bogus, class java/lang/Throwable;
+        aload_3;
+        athrow;
+        try t3, t4;
+    L37:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        aload_1;
+        ifnonnull    L42;
+        nop;
+        endtry t3, t4;
+    L42:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        goto    L54;
+        catch t3 java/lang/Exception;
+        try t5;
+        stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Exception;
+        astore_2;   // astore_2, at bci 45, that changes the type state.
+        endtry t5;
+        goto    L54;
+        catch t4 #0;
+        catch t5 #0;
+        catch t6 #0;
+        try t6;
+        stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        stack_map class java/lang/Throwable;
+        astore    4;
+        endtry t6;
+        aload    4;
+        athrow;
+    L54:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        goto    L57;
+    L57:    stack_frame_type full;
+        locals_map class java/lang/Object, class java/lang/Object, class java/lang/Object;
+        nop;
+        endtry t7;
+        return;
+        catch t7 #0;
+        stack_frame_type full;
+        stack_map class java/lang/Throwable;
+        nop;
+        athrow;
+}
+
+} // end Class BadMap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/stackMapCheck/BadMapDstore.jasm	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,79 @@
+ /*
+  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please 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 class should throw VerifyError because the StackMap for bytecode index
+ * 9 (dstore_2, line 60) is incorrect. The stack maps for bytecode indexes 9
+ * and 18 (astore_2, line 70) do not match because 9 does not supply enough
+ * locals to satisfy 18.
+ *
+ * The dstore_2 bytecode at bytecode index 9 changes the type state,
+ * preventing the stackmap mismatch.  But, if the incoming type state is used,
+ * as required by JVM Spec 8, then the verifier will detected the stackmap
+ * mismatch, and throw VerifyError.
+ */
+
+super public class BadMapDstore
+    version 51:0
+{
+
+Field blah:I;
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+        aload_0;
+        invokespecial    Method java/lang/Object."<init>":"()V";
+        return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+    stack 4 locals 4
+{
+        new    class BadMapDstore;
+        dup;
+        invokespecial    Method "<init>":"()V";
+        astore_1;
+        dconst_1;
+        try t0;
+        dstore_2;
+        aload_1;
+        iconst_5;
+        putfield    Field blah:"I";
+        endtry t0;
+        goto    L22;
+        catch t0 java/lang/Throwable;
+        stack_frame_type full;
+        locals_map class "[Ljava/lang/String;", class BadMapDstore, double;
+        stack_map class java/lang/Throwable;
+        astore_2;
+        aload_1;
+        dconst_0;
+        dstore_2;
+        pop;
+    L22:    stack_frame_type same;
+        return;
+}
+
+} // end Class BadMapDstore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/stackMapCheck/BadMapIstore.jasm	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,79 @@
+ /*
+  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please 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 class should throw VerifyError because the StackMap for bytecode index
+ * 9 (istore_2, line 60) is incorrect. The stack maps for bytecode indexes 9
+ * and 18 (astore_2, line 70) do not match because 9 does not supply enough
+ * locals to satisfy 18.
+ *
+ * The istore_2 bytecode at bytecode index 9 changes the type state,
+ * preventing the stackmap mismatch.  But, if the incoming type state is used,
+ * as required by JVM Spec 8, then the verifier will detected the stackmap
+ * mismatch, and throw VerifyError.
+ */
+
+super public class BadMapIstore
+    version 51:0
+{
+
+Field blah:I;
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+        aload_0;
+        invokespecial    Method java/lang/Object."<init>":"()V";
+        return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+    stack 2 locals 3
+{
+        new    class BadMapIstore;
+        dup;
+        invokespecial    Method "<init>":"()V";
+        astore_1;
+        iconst_2;
+        try t0;
+        istore_2;
+        aload_1;
+        iconst_5;
+        putfield    Field blah:"I";
+        endtry t0;
+        goto    L22;
+        catch t0 java/lang/Throwable;
+        stack_frame_type full;
+        locals_map class "[Ljava/lang/String;", class BadMapIstore, int;
+        stack_map class java/lang/Throwable;
+        astore_2;
+        aload_1;
+        iconst_4;
+        istore_2;
+        pop;
+    L22:    stack_frame_type same;
+        return;
+}
+
+} // end Class BadMapIstore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/stackMapCheck/StackMapCheck.java	Wed Apr 22 06:24:15 2015 +0100
@@ -0,0 +1,63 @@
+ /*
+  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please 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 7127066
+ * @summary Class verifier accepts an invalid class file
+ * @compile BadMap.jasm
+ * @compile BadMapDstore.jasm
+ * @compile BadMapIstore.jasm
+ * @run main/othervm -Xverify:all StackMapCheck
+ */
+
+public class StackMapCheck {
+    public static void main(String args[]) throws Throwable {
+
+        System.out.println("Regression test for bug 7127066");
+        try {
+            Class newClass = Class.forName("BadMap");
+            throw new RuntimeException(
+                "StackMapCheck failed, BadMap did not throw VerifyError");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("BadMap passed, VerifyError was thrown");
+        }
+
+        try {
+            Class newClass = Class.forName("BadMapDstore");
+            throw new RuntimeException(
+                "StackMapCheck failed, BadMapDstore did not throw VerifyError");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("BadMapDstore passed, VerifyError was thrown");
+        }
+
+        try {
+            Class newClass = Class.forName("BadMapIstore");
+            throw new RuntimeException(
+                "StackMapCheck failed, BadMapIstore did not throw VerifyError");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("BadMapIstore passed, VerifyError was thrown");
+        }
+    }
+}
--- a/test/serviceability/sa/jmap-hashcode/Test8028623.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java	Wed Apr 22 06:24:15 2015 +0100
@@ -33,20 +33,25 @@
 
 import com.oracle.java.testlibrary.JDKToolLauncher;
 import com.oracle.java.testlibrary.OutputBuffer;
+import com.oracle.java.testlibrary.Platform;
 import com.oracle.java.testlibrary.ProcessTools;
 
 import java.io.File;
 
 public class Test8028623 {
 
-  public static int à = 1;
+  public static int \u00CB = 1;
   public static String dumpFile = "heap.out";
 
   public static void main (String[] args) {
 
-    System.out.println(Ã);
+    System.out.println(\u00CB);
 
     try {
+        if (!Platform.shouldSAAttach()) {
+            System.out.println("SA attach not expected to work - test skipped.");
+            return;
+        }
         int pid = ProcessTools.getProcessId();
         JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
                                               .addToolArg("-F")
--- a/test/test_env.sh	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/test_env.sh	Wed Apr 22 06:24:15 2015 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-#  Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#  Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
 #  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 # 
 #  This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
-  SunOS | Linux | Darwin )
+  AIX | Darwin | Linux | SunOS )
     NULL=/dev/null
     PS=":"
     FS="/"
@@ -130,26 +130,31 @@
 fi
 
 VM_OS="unknown"
-grep "solaris" vm_version.out > ${NULL}
+grep "aix" vm_version.out > ${NULL}
 if [ $? = 0 ]
 then
-  VM_OS="solaris"
+  VM_OS="aix"
+fi
+grep "bsd" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="bsd"
 fi
 grep "linux" vm_version.out > ${NULL}
 if [ $? = 0 ]
 then
   VM_OS="linux"
 fi
+grep "solaris" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+  VM_OS="solaris"
+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}
--- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java	Wed Apr 22 06:24:15 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +23,15 @@
 
 package com.oracle.java.testlibrary;
 
+import com.oracle.java.testlibrary.Utils;
+
 public class Platform {
     private static final String osName      = System.getProperty("os.name");
     private static final String dataModel   = System.getProperty("sun.arch.data.model");
     private static final String vmVersion   = System.getProperty("java.vm.version");
     private static final String osArch      = System.getProperty("os.arch");
     private static final String vmName      = System.getProperty("java.vm.name");
+    private static final String userName    = System.getProperty("user.name");
 
     public static boolean isClient() {
         return vmName.endsWith(" Client VM");
@@ -58,6 +61,18 @@
         return dataModel.equals("64");
     }
 
+    public static boolean isAix() {
+        return isOs("aix");
+    }
+
+    public static boolean isLinux() {
+        return isOs("linux");
+    }
+
+    public static boolean isOSX() {
+        return isOs("mac");
+    }
+
     public static boolean isSolaris() {
         return isOs("sunos");
     }
@@ -66,14 +81,6 @@
         return isOs("win");
     }
 
-    public static boolean isOSX() {
-        return isOs("mac");
-    }
-
-    public static boolean isLinux() {
-        return isOs("linux");
-    }
-
     private static boolean isOs(String osname) {
         return osName.toLowerCase().startsWith(osname.toLowerCase());
     }
@@ -121,4 +128,58 @@
         return osArch;
     }
 
+    /**
+     * Return a boolean for whether we expect to be able to attach
+     * the SA to our own processes on this system.
+     */
+    public static boolean shouldSAAttach() throws Exception {
+
+        if (isAix()) {
+            return false;   // SA not implemented.
+        } else if (isLinux()) {
+            return canPtraceAttachLinux();
+        } else if (isOSX()) {
+            return canAttachOSX();
+        } else {
+            // Other platforms expected to work:
+            return true;
+        }
+    }
+
+    /**
+     * On Linux, first check the SELinux boolean "deny_ptrace" and return false
+     * as we expect to be denied if that is "1".  Then expect permission to attach
+     * if we are root, so return true.  Then return false for an expected denial
+     * if "ptrace_scope" is 1, and true otherwise.
+     */
+    public static boolean canPtraceAttachLinux() throws Exception {
+
+        // SELinux deny_ptrace:
+        String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace");
+        if (deny_ptrace != null && deny_ptrace.contains("1")) {
+            // ptrace will be denied:
+            return false;
+        }
+
+        if (userName.equals("root")) {
+            return true;
+        }
+
+        // ptrace_scope:
+        String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope");
+        if (ptrace_scope != null && ptrace_scope.contains("1")) {
+            // ptrace will be denied:
+            return false;
+        }
+
+        // Otherwise expect to be permitted:
+        return true;
+    }
+
+    /**
+     * On OSX, expect permission to attach only if we are root.
+     */
+    public static boolean canAttachOSX() throws Exception {
+        return userName.equals("root");
+    }
 }
--- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java	Fri Feb 27 09:59:29 2015 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java	Wed Apr 22 06:24:15 2015 +0100
@@ -299,6 +299,35 @@
     }
 
     /**
+     * Return the contents of the named file as a single String,
+     * or null if not found.
+     * @param filename name of the file to read
+     * @return String contents of file, or null if file not found.
+     */
+    public static String fileAsString(String filename) {
+        StringBuilder result = new StringBuilder();
+        try {
+            File file = new File(filename);
+            if (file.exists()) {
+                BufferedReader reader = new BufferedReader(new FileReader(file));
+                while (true) {
+                    String line = reader.readLine();
+                    if (line == null) {
+                        break;
+                    }
+                    result.append(line).append("\n");
+                }
+            } else {
+                // Does not exist:
+                return null;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result.toString();
+    }
+
+    /**
      * @return Unsafe instance.
      */
     public static synchronized Unsafe getUnsafe() {