changeset 11203:fdc02061f4a1

Merge
author iignatyev
date Mon, 09 May 2016 23:53:11 +0200
parents 8bfef5982e56 05c2d0b5fa7d
children adfd695e80ff
files
diffstat 24 files changed, 1771 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/lib/CompileGtest.gmk	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,116 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+GTEST_TEST_SRC := $(HOTSPOT_TOPDIR)/test/native
+GTEST_FRAMEWORK_SRC := $(SRC_ROOT)/test/fmw/gtest
+
+# On Windows, there are no internal debug symbols so must set copying to true
+# to get any at all.
+ifeq ($(OPENJDK_TARGET_OS), windows)
+  GTEST_COPY_DEBUG_SYMBOLS := true
+else
+  GTEST_COPY_DEBUG_SYMBOLS := false
+endif
+
+################################################################################
+
+GTEST_TEST_SRC_FILES := $(shell $(FIND) $(HOTSPOT_TOPDIR)/test/native -name \
+    "test*.cpp" -type f)
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+  GTEST_JVM_MAPFILE := $(JVM_MAPFILE)
+else
+  GTEST_JVM_MAPFILE := $(JVM_OUTPUTDIR)/gtest/mapfile
+
+  $(JVM_OUTPUTDIR)/gtest/symbols: $(JVM_OUTPUTDIR)/symbols
+	$(call MakeDir, $(@D))
+	( $(CAT) $< ; echo "runUnitTests" ) > $@
+
+  $(GTEST_JVM_MAPFILE): $(JVM_OUTPUTDIR)/gtest/symbols
+	$(call create-mapfile)
+endif
+
+# Disabling switch warning for clang because of test source.
+
+$(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
+    TOOLCHAIN := $(JVM_TOOLCHAIN), \
+    LIBRARY := jvm, \
+    OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
+    EXTRA_FILES := $(GTEST_TEST_SRC_FILES) \
+        $(GTEST_FRAMEWORK_SRC)/src/gtest-all.cc \
+        $(GTEST_TEST_SRC)/gtestMain.cpp, \
+    OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/objs, \
+    EXTRA_OBJECT_FILES := $(filter-out %/operator_new$(OBJ_SUFFIX), \
+        $(BUILD_LIBJVM_ALL_OBJS)), \
+    CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
+        -I$(GTEST_FRAMEWORK_SRC)/include \
+        -I$(GTEST_TEST_SRC), \
+    CFLAGS_windows := /EHsc, \
+    CFLAGS_solaris := -DGTEST_HAS_EXCEPTIONS=0 -library=stlport4, \
+    CFLAGS_macosx := -DGTEST_OS_MAC=1, \
+    CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
+    CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
+    DISABLED_WARNINGS_gcc := undef, \
+    DISABLED_WARNINGS_clang := undef switch format-nonliteral \
+        tautological-undefined-compare, \
+    DISABLED_WARNINGS_solstudio := identexpected, \
+    LDFLAGS := $(JVM_LDFLAGS), \
+    LDFLAGS_solaris := -library=stlport4 $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LIBS := $(JVM_LIBS), \
+    OPTIMIZATION := $(JVM_OPTIMIZATION), \
+    MAPFILE := $(GTEST_JVM_MAPFILE), \
+    USE_MAPFILE_FOR_SYMBOLS := true, \
+    COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
+    ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
+))
+
+TARGETS += $(BUILD_GTEST_LIBJVM)
+
+################################################################################
+
+$(eval $(call SetupNativeCompilation, BUILD_GTEST_LAUNCHER, \
+    TOOLCHAIN := $(JVM_TOOLCHAIN), \
+    PROGRAM := gtestLauncher, \
+    OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
+    EXTRA_FILES := $(GTEST_TEST_SRC)/gtestLauncher.cpp, \
+    OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/launcher-objs, \
+    CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
+        -I$(GTEST_FRAMEWORK_SRC)/include, \
+    CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
+    CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
+    LDFLAGS := $(LDFLAGS_TESTEXE), \
+    LDFLAGS_unix := -L$(JVM_OUTPUTDIR)/gtest $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LDFLAGS_solaris := -library=stlport4, \
+    LIBS_unix := -ljvm, \
+    LIBS_windows := $(JVM_OUTPUTDIR)/gtest/objs/jvm.lib, \
+    COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
+    ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
+))
+
+$(BUILD_GTEST_LAUNCHER): $(BUILD_GTEST_LIBJVM)
+
+TARGETS += $(BUILD_GTEST_LAUNCHER)
+
+################################################################################
--- a/make/lib/CompileLibraries.gmk	Mon May 09 21:27:19 2016 +0200
+++ b/make/lib/CompileLibraries.gmk	Mon May 09 23:53:11 2016 +0200
@@ -37,6 +37,10 @@
 include lib/CompileJvm.gmk
 include lib/CompileDtracePostJvm.gmk
 
+ifeq ($(BUILD_GTEST), true)
+  include lib/CompileGtest.gmk
+endif
+
 all: $(TARGETS)
 
 .PHONY: all
--- a/make/lib/JvmMapfile.gmk	Mon May 09 21:27:19 2016 +0200
+++ b/make/lib/JvmMapfile.gmk	Mon May 09 23:53:11 2016 +0200
@@ -153,20 +153,33 @@
 ################################################################################
 # Finally convert the symbol list into a platform-specific mapfile
 
-$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols
-	$(call LogInfo, Creating mapfile)
-	$(RM) $@
-        ifeq ($(OPENJDK_TARGET_OS), macosx)
-          # On macosx, we need to add a leading underscore
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  # On macosx, we need to add a leading underscore
+  define create-mapfile-work
 	  $(AWK) '{ if ($$0 ~ ".") { print "  _" $$0 } }'  < $^ > $@.tmp
-        else ifeq ($(OPENJDK_TARGET_OS), windows)
-          # On windows, add an 'EXPORTS' header
+  endef
+else ifeq ($(OPENJDK_TARGET_OS), windows)
+  # On windows, add an 'EXPORTS' header
+  define create-mapfile-work
 	  $(ECHO) "EXPORTS" > $@.tmp
 	  $(AWK) '{ if ($$0 ~ ".") { print "  " $$0 } }'  < $^ >> $@.tmp
-        else
-          # Assume standard linker script
+  endef
+else
+  # Assume standard linker script
+  define create-mapfile-work
 	  $(PRINTF) "SUNWprivate_1.1 { \n  global: \n" > $@.tmp
 	  $(AWK) '{ if ($$0 ~ ".") { print "    " $$0 ";" } }' < $^ >> $@.tmp
 	  $(PRINTF) "  local: \n    *; \n }; \n" >> $@.tmp
-        endif
+  endef
+endif
+
+define create-mapfile
+	$(call LogInfo, Creating mapfile)
+	$(call MakeDir, $(@D))
+	$(call create-mapfile-work)
+	$(RM) $@
 	$(MV) $@.tmp $@
+endef
+
+$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols
+	$(call create-mapfile)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/test/GtestImage.gmk	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+$(foreach v, $(JVM_VARIANTS), \
+  $(eval $(call SetupCopyFiles, COPY_GTEST_$v, \
+      SRC := $(HOTSPOT_OUTPUTDIR)/variant-$v/libjvm/gtest, \
+      DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
+      FILES := $(call SHARED_LIBRARY,jvm) gtestLauncher$(EXE_SUFFIX), \
+  )) \
+  $(eval TARGETS += $$(COPY_GTEST_$v)) \
+)
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+  $(foreach v, $(JVM_VARIANTS), \
+    $(eval $(call SetupCopyFiles, COPY_GTEST_MSVCR_$v, \
+        DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
+        FILES := $(MSVCR_DLL) $(MSVCP_DLL), \
+        FLATTEN := true, \
+    )) \
+    $(eval TARGETS += $$(COPY_GTEST_MSVCR_$v)) \
+    $(eval $(call SetupCopyFiles, COPY_GTEST_PDB_$v, \
+        SRC := $(HOTSPOT_OUTPUTDIR)/variant-$v/libjvm/gtest, \
+        DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
+        FILES := jvm.pdb gtestLauncher.pdb, \
+    )) \
+    $(eval TARGETS += $$(COPY_GTEST_PDB_$v)) \
+  )
+endif
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+  $(foreach v, $(JVM_VARIANTS), \
+    $(eval $(call SetupCopyFiles, COPY_GTEST_STLPORT_$v, \
+        DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
+        FILES := $(STLPORT_LIB), \
+    )) \
+    $(eval TARGETS += $$(COPY_GTEST_STLPORT_$v)) \
+  )
+endif
+
+all: $(TARGETS)
--- a/src/os/posix/vm/os_posix.cpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/os/posix/vm/os_posix.cpp	Mon May 09 23:53:11 2016 +0200
@@ -47,6 +47,12 @@
 
 // Check core dump limit and report possible place where core can be found
 void os::check_dump_limit(char* buffer, size_t bufferSize) {
+  if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
+    jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
+    VMError::record_coredump_status(buffer, false);
+    return;
+  }
+
   int n;
   struct rlimit rlim;
   bool success;
--- a/src/share/vm/memory/allocation.cpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/share/vm/memory/allocation.cpp	Mon May 09 23:53:11 2016 +0200
@@ -664,64 +664,6 @@
 // Non-product code
 
 #ifndef PRODUCT
-// The global operator new should never be called since it will usually indicate
-// a memory leak.  Use CHeapObj as the base class of such objects to make it explicit
-// that they're allocated on the C heap.
-// Commented out in product version to avoid conflicts with third-party C++ native code.
-//
-// In C++98/03 the throwing new operators are defined with the following signature:
-//
-// void* operator new(std::size_tsize) throw(std::bad_alloc);
-// void* operator new[](std::size_tsize) throw(std::bad_alloc);
-//
-// while all the other (non-throwing) new and delete operators are defined with an empty
-// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not
-// throw any exceptions (see section 18.4 of the C++ standard).
-//
-// In the new C++11/14 standard, the signature of the throwing new operators was changed
-// by completely omitting the throw clause (which effectively means they could throw any
-// exception) while all the other new/delete operators where changed to have a 'nothrow'
-// clause instead of an empty throw clause.
-//
-// Unfortunately, the support for exception specifications among C++ compilers is still
-// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to
-// override the default throwing new operator with a user operator with an empty throw()
-// clause, the MS Visual C++ compiler warns for every non-empty throw clause like
-// throw(std::bad_alloc) that it will ignore the exception specification. The following
-// operator definitions have been checked to correctly work with all currently supported
-// compilers and they should be upwards compatible with C++11/14. Therefore
-// PLEASE BE CAREFUL if you change the signature of the following operators!
-
-static void * zero = (void *) 0;
-
-void* operator new(size_t size) /* throw(std::bad_alloc) */ {
-  fatal("Should not call global operator new");
-  return zero;
-}
-
-void* operator new [](size_t size) /* throw(std::bad_alloc) */ {
-  fatal("Should not call global operator new[]");
-  return zero;
-}
-
-void* operator new(size_t size, const std::nothrow_t&  nothrow_constant) throw() {
-  fatal("Should not call global operator new");
-  return 0;
-}
-
-void* operator new [](size_t size, std::nothrow_t&  nothrow_constant) throw() {
-  fatal("Should not call global operator new[]");
-  return 0;
-}
-
-void operator delete(void* p) throw() {
-  fatal("Should not call global delete");
-}
-
-void operator delete [](void* p) throw() {
-  fatal("Should not call global delete []");
-}
-
 void AllocatedObj::print() const       { print_on(tty); }
 void AllocatedObj::print_value() const { print_value_on(tty); }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/operator_new.cpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "utilities/debug.hpp"
+
+#include <new>
+
+//--------------------------------------------------------------------------------------
+// Non-product code
+
+#ifndef PRODUCT
+// The global operator new should never be called since it will usually indicate
+// a memory leak.  Use CHeapObj as the base class of such objects to make it explicit
+// that they're allocated on the C heap.
+// Commented out in product version to avoid conflicts with third-party C++ native code.
+//
+// In C++98/03 the throwing new operators are defined with the following signature:
+//
+// void* operator new(std::size_tsize) throw(std::bad_alloc);
+// void* operator new[](std::size_tsize) throw(std::bad_alloc);
+//
+// while all the other (non-throwing) new and delete operators are defined with an empty
+// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not
+// throw any exceptions (see section 18.4 of the C++ standard).
+//
+// In the new C++11/14 standard, the signature of the throwing new operators was changed
+// by completely omitting the throw clause (which effectively means they could throw any
+// exception) while all the other new/delete operators where changed to have a 'nothrow'
+// clause instead of an empty throw clause.
+//
+// Unfortunately, the support for exception specifications among C++ compilers is still
+// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to
+// override the default throwing new operator with a user operator with an empty throw()
+// clause, the MS Visual C++ compiler warns for every non-empty throw clause like
+// throw(std::bad_alloc) that it will ignore the exception specification. The following
+// operator definitions have been checked to correctly work with all currently supported
+// compilers and they should be upwards compatible with C++11/14. Therefore
+// PLEASE BE CAREFUL if you change the signature of the following operators!
+
+static void * zero = (void *) 0;
+
+void* operator new(size_t size) /* throw(std::bad_alloc) */ {
+  fatal("Should not call global operator new");
+  return zero;
+}
+
+void* operator new [](size_t size) /* throw(std::bad_alloc) */ {
+  fatal("Should not call global operator new[]");
+  return zero;
+}
+
+void* operator new(size_t size, const std::nothrow_t&  nothrow_constant) throw() {
+  fatal("Should not call global operator new");
+  return 0;
+}
+
+void* operator new [](size_t size, std::nothrow_t&  nothrow_constant) throw() {
+  fatal("Should not call global operator new[]");
+  return 0;
+}
+
+void operator delete(void* p) throw() {
+  fatal("Should not call global delete");
+}
+
+void operator delete [](void* p) throw() {
+  fatal("Should not call global delete []");
+}
+
+#endif // Non-product
--- a/src/share/vm/runtime/globals.hpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/share/vm/runtime/globals.hpp	Mon May 09 23:53:11 2016 +0200
@@ -2070,6 +2070,9 @@
   notproduct(bool, VerboseInternalVMTests, false,                           \
           "Turn on logging for internal VM tests.")                         \
                                                                             \
+  product(bool, ExecutingUnitTests, false,                                  \
+          "Whether the JVM is running unit tests or not")                   \
+                                                                            \
   product_pd(bool, UseTLAB, "Use thread-local object allocation")           \
                                                                             \
   product_pd(bool, ResizeTLAB,                                              \
--- a/src/share/vm/services/management.cpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/share/vm/services/management.cpp	Mon May 09 23:53:11 2016 +0200
@@ -1609,8 +1609,8 @@
   }
   char* name = java_lang_String::as_utf8_string(fn);
 
-  FormatBuffer<80> err_msg("%s", "");
-  int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, err_msg);
+  FormatBuffer<80> error_msg("%s", "");
+  int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, error_msg);
 
   if (succeed != Flag::SUCCESS) {
     if (succeed == Flag::MISSING_VALUE) {
@@ -1619,7 +1619,7 @@
     } else {
       // all the other errors are reported as IAE with the appropriate error message
       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg.buffer());
+                error_msg.buffer());
     }
   }
   assert(succeed == Flag::SUCCESS, "Setting flag should succeed");
--- a/src/share/vm/utilities/debug.cpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/share/vm/utilities/debug.cpp	Mon May 09 23:53:11 2016 +0200
@@ -58,6 +58,8 @@
 #include "trace/tracing.hpp"
 #endif
 
+#include <stdio.h>
+
 #ifndef ASSERT
 #  ifdef _DEBUG
    // NOTE: don't turn the lines below into a comment -- if you're getting
@@ -187,7 +189,7 @@
     return true;
   }
 
-  if (!is_error_reported()) {
+  if (!is_error_reported() && !SuppressFatalErrorMessage) {
     // print a friendly hint:
     fdStream out(defaultStream::output_fd());
     out.print_raw_cr("# To suppress the following error report, specify this argument");
@@ -262,6 +264,21 @@
   report_vm_error(file, line, "Unimplemented()");
 }
 
+#ifdef ASSERT
+bool is_executing_unit_tests() {
+  return ExecutingUnitTests;
+}
+
+void report_assert_msg(const char* msg, ...) {
+  va_list ap;
+  va_start(ap, msg);
+
+  fprintf(stderr, "assert failed: %s\n", err_msg(FormatBufferDummy(), msg, ap).buffer());
+
+  va_end(ap);
+}
+#endif // ASSERT
+
 void report_untested(const char* file, int line, const char* message) {
 #ifndef PRODUCT
   warning("Untested: %s in %s: %d\n", message, file, line);
--- a/src/share/vm/utilities/debug.hpp	Mon May 09 21:27:19 2016 +0200
+++ b/src/share/vm/utilities/debug.hpp	Mon May 09 23:53:11 2016 +0200
@@ -46,11 +46,15 @@
   FormatBufferResource(const char * format, ...) ATTRIBUTE_PRINTF(2, 3);
 };
 
+class FormatBufferDummy {};
+
 // Use stack for buffer
 template <size_t bufsz = FormatBufferBase::BufferSize>
 class FormatBuffer : public FormatBufferBase {
  public:
   inline FormatBuffer(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
+  // since va_list is unspecified type (can be char*), we use FormatBufferDummy to disambiguate these constructors
+  inline FormatBuffer(FormatBufferDummy dummy, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0);
   inline void append(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3);
   inline void print(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3);
   inline void printv(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
@@ -75,6 +79,11 @@
 }
 
 template <size_t bufsz>
+FormatBuffer<bufsz>::FormatBuffer(FormatBufferDummy dummy, const char * format, va_list ap) : FormatBufferBase(_buffer) {
+  jio_vsnprintf(_buf, bufsz, format, ap);
+}
+
+template <size_t bufsz>
 FormatBuffer<bufsz>::FormatBuffer() : FormatBufferBase(_buffer) {
   _buf[0] = '\0';
 }
@@ -119,11 +128,13 @@
 #define vmassert(p, ...)                                                       \
 do {                                                                           \
   if (!(p)) {                                                                  \
+    if (is_executing_unit_tests()) {                                           \
+      report_assert_msg(__VA_ARGS__);                                          \
+    }                                                                          \
     report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", __VA_ARGS__); \
     BREAKPOINT;                                                                \
   }                                                                            \
 } while (0)
-
 #endif
 
 // For backward compatibility.
@@ -210,10 +221,16 @@
 // ATTRIBUTE_PRINTF works with gcc >= 4.8 and any other compiler.
 void report_vm_error(const char* file, int line, const char* error_msg,
                      const char* detail_fmt, ...) ATTRIBUTE_PRINTF(4, 5);
+#ifdef ASSERT
+void report_assert_msg(const char* msg, ...) ATTRIBUTE_PRINTF(1, 2);
+#endif // ASSERT
 #else
 // GCC < 4.8 warns because of empty format string.  Warning can not be switched off selectively.
 void report_vm_error(const char* file, int line, const char* error_msg,
                      const char* detail_fmt, ...);
+#ifdef ASSERT
+void report_assert_msg(const char* msg, ...);
+#endif // ASSERT
 #endif
 void report_vm_status_error(const char* file, int line, const char* error_msg,
                             int status, const char* detail);
@@ -225,6 +242,11 @@
 void report_unimplemented(const char* file, int line);
 void report_untested(const char* file, int line, const char* message);
 
+#ifdef ASSERT
+// unit test support
+bool is_executing_unit_tests();
+#endif // ASSERT
+
 void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2);
 
 // Compile-time asserts.  Cond must be a compile-time constant expression that
--- a/test/Makefile	Mon May 09 21:27:19 2016 +0200
+++ b/test/Makefile	Mon May 09 23:53:11 2016 +0200
@@ -52,6 +52,11 @@
 WC        = wc
 ZIP       = zip
 
+define NEWLINE
+
+
+endef
+
 # Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
 UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
 ifeq ($(UNAME_S), SunOS)
@@ -427,6 +432,20 @@
 
 ################################################################
 
+# Run the native gtest tests from the test image
+
+hotspot_gtest:
+	$(foreach v, $(JVM_VARIANTS), \
+	  $(MAKE) hotspot_gtest$v $(NEWLINE) )
+
+hotspot_gtestserver hotspot_gtestclient hotspot_gtestminimal: hotspot_gtest%:
+	$(TESTNATIVE_DIR)/hotspot/gtest/$*/gtestLauncher \
+	    -jdk $(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")
+
+PHONY_LIST += hotspot_gtest hotspot_gtestserver hotspot_gtestclient \
+    hotspot_gtestminimal
+
+################################################################
 # Phony targets (e.g. these are not filenames)
 .PHONY: all clean prep $(PHONY_LIST)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/GC.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+import gc.testlibrary.Helpers;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Provides methods to initiate GC of requested type and
+ * checks for states of humongous and non-humongous soft/weak externally
+ * referenced objects after GCs
+ */
+public enum GC {
+
+    YOUNG_GC {
+        @Override
+        public Runnable get() {
+            return WHITE_BOX::youngGC;
+        }
+
+        public Consumer<ReferenceInfo<Object[]>> getChecker() {
+            return getCheckerImpl(false, false, true, false);
+        }
+
+        @Override
+        public List<String> shouldContain() {
+            return Arrays.asList(GCTokens.WB_INITIATED_YOUNG_GC);
+        }
+
+        @Override
+        public List<String> shouldNotContain() {
+            return Arrays.asList(GCTokens.WB_INITIATED_MIXED_GC, GCTokens.FULL_GC, GCTokens.WB_INITIATED_CMC,
+                    GCTokens.CMC, GCTokens.YOUNG_GC);
+        }
+    },
+    FULL_GC {
+        @Override
+        public Runnable get() {
+            return System::gc;
+        }
+
+        public Consumer<ReferenceInfo<Object[]>> getChecker() {
+            return getCheckerImpl(true, false, true, false);
+        }
+
+        @Override
+        public List<String> shouldContain() {
+            return Arrays.asList(GCTokens.FULL_GC);
+        }
+
+        @Override
+        public List<String> shouldNotContain() {
+            return Arrays.asList(GCTokens.WB_INITIATED_YOUNG_GC, GCTokens.WB_INITIATED_MIXED_GC,
+                    GCTokens.WB_INITIATED_CMC, GCTokens.CMC, GCTokens.YOUNG_GC);
+        }
+    },
+
+    FULL_GC_MEMORY_PRESSURE {
+        @Override
+        public Runnable get() {
+            return WHITE_BOX::fullGC;
+        }
+
+        public Consumer<ReferenceInfo<Object[]>> getChecker() {
+            return getCheckerImpl(true, true, true, true);
+        }
+
+        @Override
+        public List<String> shouldContain() {
+            return Arrays.asList(GCTokens.FULL_GC_MEMORY_PRESSURE);
+        }
+
+        @Override
+        public List<String> shouldNotContain() {
+            return Arrays.asList(GCTokens.WB_INITIATED_YOUNG_GC, GCTokens.WB_INITIATED_MIXED_GC,
+                    GCTokens.WB_INITIATED_CMC, GCTokens.CMC, GCTokens.YOUNG_GC, GCTokens.FULL_GC);
+        }
+    };
+
+    protected String getErrorMessage(ReferenceInfo<Object[]> ref, boolean expectedNull, String gcType) {
+        return String.format("Externally effectively %s referenced %shumongous object was%s deleted after %s",
+                (ref.softlyReachable ? "soft" : "weak"), (ref.effectiveHumongous ? "" : "non-"),
+                (expectedNull ? " not" : ""), gcType);
+    }
+
+    protected Consumer<ReferenceInfo<Object[]>> getCaseCheck(boolean expectedNull) {
+        return expectedNull
+                ? r -> Asserts.assertNull(r.reference.get(), getErrorMessage(r, true, name()))
+                : r -> Asserts.assertNotNull(r.reference.get(), getErrorMessage(r, false, name()));
+    }
+
+    protected Consumer<ReferenceInfo<Object[]>> getCheckerImpl(boolean weakH, boolean softH,
+                                                               boolean weakS, boolean softS) {
+        return new Checker(getCaseCheck(weakH), getCaseCheck(softH), getCaseCheck(weakS), getCaseCheck(softS));
+    }
+
+    protected String getGcLogName(String prefix) {
+        return prefix + "_" + name() + ".gc.log";
+    }
+
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    /**
+     * @return method to initiate GC
+     */
+    public abstract Runnable get();
+
+    /**
+     * @return checker for objects' states after GC
+     */
+    public abstract Consumer<ReferenceInfo<Object[]>> getChecker();
+
+    /**
+     * @return list of tokens that should be contained in gc log after gc of specified type
+     */
+    public abstract List<String> shouldContain();
+
+    /**
+     * @return list of tokens that should not be contained in gc log after gc of specified type
+     */
+    public abstract List<String> shouldNotContain();
+
+
+    /**
+     * Checks object' state after gc
+     * Contains 4 Consumers which are called depending on humongous/non-humongous and
+     * external weak/soft referenced objects
+     */
+    private static class Checker implements Consumer<ReferenceInfo<Object[]>> {
+        // 4 consumers with checks for (humongous /simple objects)*(weak/soft referenced)
+        final Consumer<ReferenceInfo<Object[]>> weakHumongousCheck;
+        final Consumer<ReferenceInfo<Object[]>> softHumongousCheck;
+        final Consumer<ReferenceInfo<Object[]>> weakSimpleCheck;
+        final Consumer<ReferenceInfo<Object[]>> softSimpleCheck;
+
+        public Checker(Consumer<ReferenceInfo<Object[]>> weakHumongousCheck,
+                       Consumer<ReferenceInfo<Object[]>> softHumongousCheck,
+                       Consumer<ReferenceInfo<Object[]>> weakSimpleCheck,
+                       Consumer<ReferenceInfo<Object[]>> softSimpleCheck) {
+            this.weakHumongousCheck = weakHumongousCheck;
+            this.softHumongousCheck = softHumongousCheck;
+            this.weakSimpleCheck = weakSimpleCheck;
+            this.softSimpleCheck = softSimpleCheck;
+        }
+
+        public void accept(ReferenceInfo<Object[]> ref) {
+
+            System.out.println("reference.get() returned " + ref.reference.get());
+            if (ref.effectiveHumongous && ref.softlyReachable) {
+                System.out.println("soft and humongous");
+                softHumongousCheck.accept(ref);
+            }
+
+            if (ref.effectiveHumongous && !ref.softlyReachable) {
+                System.out.println("weak and humongous");
+                weakHumongousCheck.accept(ref);
+
+            }
+
+            if (!ref.effectiveHumongous && ref.softlyReachable) {
+                System.out.println("soft and non-humongous");
+                softSimpleCheck.accept(ref);
+            }
+
+            if (!ref.effectiveHumongous && !ref.softlyReachable) {
+                System.out.println("weak and non-humongous");
+                weakSimpleCheck.accept(ref);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/GCTokens.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+/**
+ * Contains tokens that could appear in gc log
+ */
+public final class GCTokens {
+    // Private c-tor to prevent instantiating
+    private GCTokens() {
+    }
+
+    public static final String WB_INITIATED_YOUNG_GC = "Young (WhiteBox Initiated Young GC)";
+    public static final String WB_INITIATED_MIXED_GC = "Pause Mixed (WhiteBox Initiated Young GC)";
+    public static final String WB_INITIATED_CMC = "WhiteBox Initiated Concurrent Mark";
+    public static final String FULL_GC = "Full (System.gc())";
+    public static final String FULL_GC_MEMORY_PRESSURE = "WhiteBox Initiated Full GC";
+    public static final String CMC = "Concurrent Mark)";
+    public static final String YOUNG_GC = "GC pause (young)";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/ObjectGraph.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class ObjectGraph {
+
+    private ObjectGraph() {
+    }
+
+    public enum ReferenceType {
+        NONE,
+        WEAK,
+        SOFT,
+        STRONG;
+    }
+
+    /**
+     * Performs operation on all nodes that are reachable from initial ones
+     *
+     * @param nodes     initial nodes
+     * @param operation operation
+     */
+    public static void propagateTransitiveProperty(Set<Object[]> nodes, Consumer<Object[]> operation) {
+        Deque<Object[]> roots = new ArrayDeque<>();
+        nodes.stream().forEach(roots::push);
+        ObjectGraph.enumerateAndMark(roots, operation);
+    }
+
+    /**
+     * Connects graph's vertexes with single-directed (vertex -> neighbour) link
+     *
+     * @param vertex    who is connected
+     * @param neighbour connected to whom
+     */
+    private static void connectVertexes(Object[] vertex, Object[] neighbour) {
+
+        // check if vertex array is full
+        if (vertex[vertex.length - 1] != null) {
+            throw new Error("Array is full and no connections could be added");
+        }
+        int i = 0;
+        while (vertex[i] != null) {
+            ++i;
+        }
+        vertex[i] = neighbour;
+    }
+
+
+    /**
+     * Builds object graph using description from list of parsed nodes. Graph uses Object[] as nodes, first n elements
+     * of array are links to connected nodes, others are null. Then runs visitors on generated graph
+     *
+     * @param parsedNodes             list of nodes' description
+     * @param visitors                visitors that will visit each node of generated graph
+     * @param humongousAllocationSize size of humongous node
+     * @param simpleAllocationSize    size of simple (non-humongous) node
+     * @return root reference to generated graph
+     */
+    public static Object[] generateObjectNodes(List<TestcaseData.FinalParsedNode> parsedNodes,
+                                               Map<Predicate<TestcaseData.FinalParsedNode>,
+                                                       BiConsumer<TestcaseData.FinalParsedNode, Object[][]>> visitors,
+                                               int humongousAllocationSize, int simpleAllocationSize) {
+
+        Object[][] objectNodes = new Object[parsedNodes.size()][];
+
+        // Allocating nodes on Object[]
+        for (int i = 0; i < parsedNodes.size(); ++i) {
+            objectNodes[i] = new Object[(parsedNodes.get(i).isHumongous ?
+                    humongousAllocationSize : simpleAllocationSize)];
+        }
+
+        // Connecting nodes on allocated on Object[]
+        for (int i = 0; i < parsedNodes.size(); ++i) {
+            for (int j = 0; j < parsedNodes.get(i).getConnectedTo().size(); ++j) {
+                connectVertexes(objectNodes[i], objectNodes[parsedNodes.get(i).getConnectedTo().get(j)]);
+            }
+        }
+
+        // Calling visitors
+        visitors.entrySet()
+                .stream()
+                .forEach(
+                        entry -> parsedNodes.stream()
+                                .filter(parsedNode -> entry.getKey().test(parsedNode))
+                                .forEach(node -> entry.getValue().accept(node, objectNodes))
+                );
+
+        return objectNodes[0];
+    }
+
+    /**
+     * Enumerates graph starting with provided vertexes. All vertexes that are reachable from the provided ones are
+     * marked
+     *
+     * @param markedParents provided vertexes
+     * @param markVertex    lambda which marks vertexes
+     */
+    public static void enumerateAndMark(Deque<Object[]> markedParents,
+                                        Consumer<Object[]> markVertex) {
+        Map<Object[], Boolean> isVisited = new HashMap<>();
+        while (!markedParents.isEmpty()) {
+            Object[] vertex = markedParents.pop();
+            if (vertex == null || isVisited.containsKey(vertex)) {
+                continue;
+            }
+            isVisited.put(vertex, true);
+            markVertex.accept(vertex);
+
+            for (int i = 0; i < vertex.length; ++i) {
+                if (vertex[i] == null) {
+                    break;
+                }
+                markedParents.add((Object[]) vertex[i]);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/README	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 test checks that after different type of GC unreachable objects behave as expected:
+
+1. Young GC - weakly referenced non-humongous objects are collected, other objects are not collected.
+
+2. Full GC - weakly referenced non-humongous and humongous objects are collected, softly referenced non-humongous and
+             humongous objects are not collected.
+
+3. Full GC with memory pressure - weakly and softly referenced non-humongous and humongous objects are collected.
+
+The test gets gc type as a command line argument.
+Then the test allocates object graph in heap (currently testing scenarios are pre-generated and stored in
+TestcaseData.getPregeneratedTestcases()) with TestObjectGraphAfterGC::allocateObjectGraph.
+
+Since we are testing humongous objects we need pretty unusual nodes - arrays of Object.
+We need this since only large enough array could be Humongous object (in fact class with huge amount of fields is
+humongous too but it's for other tests).
+ObjectGraph class generates object graph with Object[] nodes. It also provides a way to collect
+information about each node using "visitor" pattern.
+
+Using visitors we build Set of ReferenceInfo instances which contains the following information:
+reference - external weak/soft reference to graph's node
+graphId and nodeId - graph's and node's ids - we need this for error handling
+softlyReachable - is node effectively referenced by external soft reference. It could be when external
+soft reference or when this node is reachable from node that exteranally referenced by soft reference
+effectiveHumongous - if node behaves effectively humongous.  It could be when node is humongous
+or when this node is reachable from humongous node.
+
+When we leave TestObjectGraphAfterGC::allocateObjectGraph we make graph reachable only with references from Set of
+ReferenceInfo instances.
+
+We run specified gc and check that each instance of ReferenceInfo set behaves as expected.
+Then we check that gc log file contains expected tokens and doesn't contain tokens that it should not contain.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/ReferenceInfo.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+import java.lang.ref.Reference;
+
+/**
+ * Immutable structure that holds the following information about graph's node
+ * reference - weak/soft reference to graph's node
+ * graphId and nodeId - graph's and node's ids - we need this for error handling
+ * softlyReachable - is node effectively referenced by external soft reference. It could be when external
+ * soft reference or when this node is reachable from node that externally referenced by soft reference
+ * effectiveHumongous - if node behaves effectively humongous.  It could be when node is humongous
+ * or when this node is reachable from humongous node.
+ *
+ * @param <T> - actual type of node
+ */
+public class ReferenceInfo<T> {
+    public final Reference<T> reference;
+    public final String graphId;
+    public final String nodeId;
+    public final boolean softlyReachable;
+    public final boolean effectiveHumongous;
+
+    public ReferenceInfo(Reference<T> reference, String graphId, String nodeId, boolean softlyReachable,
+                         boolean effectiveHumongous) {
+        this.reference = reference;
+        this.graphId = graphId;
+        this.nodeId = nodeId;
+        this.softlyReachable = softlyReachable;
+        this.effectiveHumongous = effectiveHumongous;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Node %s is effectively %shumongous and effectively %ssoft referenced\n"
+                        + "\tReference type is %s and it points to %s", nodeId,
+                (effectiveHumongous ? "" : "non-"), (softlyReachable ? "" : "non-"),
+                reference.getClass().getSimpleName(), reference.get());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+import jdk.test.lib.OutputAnalyzer;
+import sun.hotspot.WhiteBox;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+
+/**
+ * @test TestObjectGraphAfterGC
+ * @summary Checks that objects' graph behave as expected after gc
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @library /testlibrary /test/lib /
+ * @modules java.management java.base/jdk.internal.misc
+ * @build sun.hotspot.WhiteBox
+ *        gc.testlibrary.Helpers
+ *        gc.g1.humongousObjects.objectGraphTest.GCTokens
+ *        gc.g1.humongousObjects.objectGraphTest.ReferenceInfo
+ *        gc.g1.humongousObjects.objectGraphTest.GC
+ *        gc.g1.humongousObjects.objectGraphTest.ObjectGraph
+ *        gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ *
+ * @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=1M -Xlog:gc*=debug:file=TestObjectGraphAfterGC_YOUNG_GC.gc.log
+ * gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC YOUNG_GC
+ *
+ * @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=1M -Xlog:gc=info:file=TestObjectGraphAfterGC_FULL_GC.gc.log
+ * gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC FULL_GC
+ *
+ * @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=1M -Xlog:gc=info:file=TestObjectGraphAfterGC_FULL_GC_MEMORY_PRESSURE.gc.log
+ * gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC FULL_GC_MEMORY_PRESSURE
+ *
+ */
+
+/**
+ * Checks that objects' graph behave as expected after gc
+ * See README file for detailed info on test's logic
+ */
+public class TestObjectGraphAfterGC {
+
+    private static final int simpleAllocationSize = 1024;
+
+    /**
+     * Entry point
+     *
+     * @param args - first argument - gc name
+     */
+    public static void main(String[] args) {
+
+        if (args.length < 1) {
+            throw new Error("Expected gc name wasn't provided as command line argument");
+        }
+
+        GC gcType = GC.valueOf(args[0].toUpperCase());
+
+        System.out.println("Testing " + gcType.name());
+
+        TestcaseData.getPregeneratedTestcases().stream().forEach(testcase -> {
+            System.out.println("Testcase: " + testcase);
+
+            try {
+                TestObjectGraphAfterGC.doTesting(testcase, gcType.get(), gcType.getChecker(),
+                        gcType.getGcLogName(TestObjectGraphAfterGC.class.getSimpleName()), gcType.shouldContain(),
+                        gcType.shouldNotContain());
+            } catch (IOException e) {
+                throw new Error("Problems trying to find or open " + TestObjectGraphAfterGC.class.getSimpleName()
+                        + ".gc.log", e);
+            }
+            System.out.println(" Passed");
+        });
+    }
+
+    /**
+     * Implements testing with 3 methods - allocateObjectGraph, checkResults and checkGCLog
+     *
+     * @param testcaseData     testcase in the following notation:
+     *                         H - humongous node
+     *                         S - non-humongous node
+     *                         s - external soft reference
+     *                         w - external weak reference
+     *                         Hs->Sw - 1st node is humongous, externally soft referenced and strong references to
+     *                         non-humongous node 2 which is externally weak referenced
+     *                         H->1 - humongous node connects to the first node of chain
+     * @param doGC             method that initiates gc
+     * @param checker          consumer that checks node's state after gc and throws Error if it's wrong
+     * @param gcLogName        name of gc log
+     * @param shouldContain    list of tokens that should be contained in gc log
+     * @param shouldNotContain list of tokens that should not be contained in gc log
+     * @throws IOException if there are some issues with gc log
+     */
+    private static void doTesting(String testcaseData, Runnable doGC, Consumer<ReferenceInfo<Object[]>> checker,
+                                  String gcLogName, List<String> shouldContain, List<String> shouldNotContain)
+            throws IOException {
+        Set<ReferenceInfo<Object[]>> nodeData = allocateObjectGraph(testcaseData);
+        doGC.run();
+        checkResults(nodeData, checker);
+        checkGCLog(gcLogName, shouldContain, shouldNotContain);
+    }
+
+    /**
+     * Allocates a number of objects of humongous and regular size and links then with strong references.
+     * How many objects to create, their size and links between them is encoded in the given parameters.
+     * As the result an object graph will be created.
+     * For the testing purpose for each created object (a graph node) an extra ReferenceInfo object will be created.
+     * The ReferenceInfo instances will contain either weak or soft reference to the graph node.
+     *
+     * @param testcaseData testcase in the
+     *                     <p>
+     *                     H - humongous node
+     *                     S - non-humongous node
+     *                     s - external soft reference
+     *                     w - external weak reference
+     *                     Hs->Sw - 1st node is humongous, externally soft referenced and strong references to
+     *                     non-humongous node 2 which is externally weak referenced
+     *                     H->1 - humongous node connects to the first node of chain
+     * @return set of ReferenceInfo objects containing weak/soft reference to the graph node and other data on how
+     * objects should behave after gc
+     */
+    private static Set<ReferenceInfo<Object[]>> allocateObjectGraph(String testcaseData) {
+        Map<Object[], String> nodeIds = new HashMap<>();
+        Set<Object[]> humongousNodes = new HashSet<>();
+        Set<Object[]> externalSoftReferenced = new HashSet<>();
+        Set<Object[]> externalWeakReferenced = new HashSet<>();
+
+        Map<Predicate<TestcaseData.FinalParsedNode>, BiConsumer<TestcaseData.FinalParsedNode, Object[][]>> visitors
+                = new HashMap<>();
+
+        visitors.put((parsedNode -> true),
+                (parsedNode, objects) -> nodeIds.put(objects[Integer.valueOf(parsedNode.id)], parsedNode.id)
+        );
+
+        visitors.put((parsedNode -> parsedNode.isHumongous),
+                (parsedNode, objects) -> humongousNodes.add(objects[Integer.valueOf(parsedNode.id)])
+        );
+
+        visitors.put(parsedNode -> parsedNode.getReferencesTypes().stream().
+                        anyMatch(referenceType -> referenceType == ObjectGraph.ReferenceType.SOFT),
+                (parsedNode, objects) -> externalSoftReferenced.add(objects[Integer.valueOf(parsedNode.id)])
+        );
+
+        visitors.put(parsedNode -> parsedNode.getReferencesTypes().stream().
+                        anyMatch(referenceType -> referenceType == ObjectGraph.ReferenceType.WEAK),
+                (parsedNode, objects) -> externalWeakReferenced.add(objects[Integer.valueOf(parsedNode.id)])
+        );
+
+        List<TestcaseData.FinalParsedNode> internalParsedNodes = TestcaseData.parse(testcaseData);
+
+        Object[] root = ObjectGraph.generateObjectNodes(internalParsedNodes, visitors,
+                WhiteBox.getWhiteBox().g1RegionSize(), simpleAllocationSize);
+
+        ObjectGraph.propagateTransitiveProperty(humongousNodes, humongousNodes::add);
+        Set<Object[]> effectiveSoftReferenced = new HashSet<>();
+        ObjectGraph.propagateTransitiveProperty(externalSoftReferenced, effectiveSoftReferenced::add);
+
+        // Create external references
+        ReferenceQueue<Object[]> referenceQueue = new ReferenceQueue<>();
+        Set<Reference<Object[]>> externalRefs = new HashSet<>();
+
+        externalWeakReferenced.stream()
+                .forEach(objects -> externalRefs.add(new WeakReference<>(objects, referenceQueue)));
+        externalSoftReferenced.stream()
+                .forEach(objects -> externalRefs.add(new SoftReference<>(objects, referenceQueue)));
+
+        return externalRefs.stream()
+                .map(ref -> new ReferenceInfo<>(ref, testcaseData, nodeIds.get(ref.get()),
+                        effectiveSoftReferenced.contains(ref.get()), humongousNodes.contains(ref.get())))
+                .collect(Collectors.toSet());
+
+    }
+
+    /**
+     * Checks that object' state after gc is as expected
+     *
+     * @param nodeData array with information about nodes
+     * @param checker  consumer that checks node's state after gc and throws Error if it's wrong
+     */
+    private static void checkResults(Set<ReferenceInfo<Object[]>> nodeData, Consumer<ReferenceInfo<Object[]>> checker) {
+        nodeData.stream().forEach(checker::accept);
+    }
+
+    /**
+     * Checks that gc log contains what we expected and does not contain what we didn't expect
+     *
+     * @param gcLogName        gc log name
+     * @param shouldContain    list of tokens that should be contained in gc log
+     * @param shouldNotContain list of tokens that should not be contained in gc log
+     * @throws IOException if there are some issues with gc log
+     */
+    private static void checkGCLog(String gcLogName, List<String> shouldContain, List<String> shouldNotContain)
+            throws IOException {
+
+        if (gcLogName == null) {
+            return;
+        }
+        String gcLog = new String(Files.readAllBytes(new File(gcLogName).toPath()));
+
+        OutputAnalyzer outputAnalyzer = new OutputAnalyzer(gcLog, "");
+
+        shouldContain.stream().forEach(outputAnalyzer::shouldContain);
+        shouldNotContain.stream().forEach(outputAnalyzer::shouldNotContain);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/humongousObjects/objectGraphTest/TestcaseData.java	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 gc.g1.humongousObjects.objectGraphTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public final class TestcaseData {
+    /**
+     * Temporary node description used during parsing
+     */
+    private static class InternalParsedNode {
+        public String id;
+        public final ArrayList<Integer> connectedTo = new ArrayList<>();
+        public final ArrayList<Integer> connectedFrom = new ArrayList<>();
+        public final List<ObjectGraph.ReferenceType> referencesTypes = new ArrayList<>();
+        public boolean isHumongous;
+    }
+
+    /**
+     * Immutable node description.
+     * Contains:
+     * Node id
+     * Humongous flag
+     * List of external references' types
+     * List of nodes connected to
+     */
+    public static class FinalParsedNode {
+        public final String id;
+        public final boolean isHumongous;
+        private final List<ObjectGraph.ReferenceType> referencesTypes;
+        private final ArrayList<Integer> connectedTo;
+
+
+        public FinalParsedNode(InternalParsedNode internalParsedNode) {
+            referencesTypes = internalParsedNode.referencesTypes;
+            connectedTo = internalParsedNode.connectedTo;
+            id = internalParsedNode.id;
+            isHumongous = internalParsedNode.isHumongous;
+        }
+
+        public List<ObjectGraph.ReferenceType> getReferencesTypes() {
+            return Collections.unmodifiableList(referencesTypes);
+        }
+
+        public List<Integer> getConnectedTo() {
+            return Collections.unmodifiableList(connectedTo);
+        }
+    }
+
+    /**
+     * @param testcaseDesc testcase in the following notation:
+     *                     H - humongous node
+     *                     S - non-humongous node
+     *                     s - external soft reference
+     *                     w - external weak reference
+     *                     Hs->Sw - 1st node is humongous, externally soft referenced and strong references to non-humongous node 2 which is
+     *                     externally weak referenced
+     *                     H->1 - humongous node connects to the first node of chain
+     * @return list of nodes description in FinalParsedNode structure
+     */
+    public static List<FinalParsedNode> parse(String testcaseDesc) {
+        String[] nodes = testcaseDesc.split("-");
+        List<InternalParsedNode> internalParsedNodeList = new ArrayList<>();
+
+        for (int i = 0; i < nodes.length; ++i) {
+            String node = nodes[i];
+            InternalParsedNode nd;
+            if (node.contains("1")) {
+                nd = internalParsedNodeList.get(0);
+
+            } else {
+                nd = new InternalParsedNode();
+                internalParsedNodeList.add(nd);
+                nd.id = String.valueOf(i);
+            }
+
+            if (node.startsWith(">")) {
+                nd.connectedFrom.add(i - 1);
+            }
+            if (node.endsWith("<")) {
+                nd.connectedFrom.add(i + 1);
+            }
+            if (node.contains("w")) {
+                nd.referencesTypes.add(ObjectGraph.ReferenceType.WEAK);
+            }
+
+            if (node.contains("s")) {
+                nd.referencesTypes.add(ObjectGraph.ReferenceType.SOFT);
+            }
+            if (node.contains("H")) {
+                nd.isHumongous = true;
+            }
+
+            if (node.contains("S")) {
+                nd.isHumongous = false;
+            }
+        }
+
+        // we have connectedFrom but we need to get connectedTo
+        for (int i = 0; i < internalParsedNodeList.size(); ++i) {
+            for (Integer reference : internalParsedNodeList.get(i).connectedFrom) {
+                internalParsedNodeList.get(reference).connectedTo.add(i);
+            }
+        }
+
+        List<FinalParsedNode> finalParsedNodes = internalParsedNodeList.stream().map(FinalParsedNode::new)
+                .collect(Collectors.toList());
+
+        return finalParsedNodes;
+    }
+
+    /**
+     * @return List of pregenerated testing cases
+     */
+    public static List<String> getPregeneratedTestcases() {
+        return Arrays.asList(
+                "Hw",
+                "Sw",
+                "Sw->Hw",
+                "Hw->Sw",
+                "Sw<->Hw",
+                "Sw<->Sw",
+                "Hw->Sw->Sw",
+                "Hw->Sw->Sw",
+                "Sw->Hw->Sw",
+                "Hw->Sw->Sw->1",
+                "Sw->Hw->Sw->1",
+                "Sw->Hw->Hw->1",
+                "Sw<->Hw<->Hw->1",
+                "Sw<->Hw<->Sw->1",
+                "Sw->Hw<->Sw",
+                "Hs",
+                "Ss",
+                "Ss->Hs",
+                "Hs->Ss",
+                "Ss<->Hs",
+                "Ss<->Ss",
+                "Hs->Ss->Ss",
+                "Hs->Ss->Ss",
+                "Ss->Hs->Ss",
+                "Hs->Ss->Ss->1",
+                "Ss->Hs->Ss->1",
+                "Ss->Hs->Hs->1",
+                "Ss<->Hs<->Hs->1",
+                "Ss<->Hs<->Ss->1",
+                "Ss->Hs<->Ss",
+                "Ss->Hw",
+                "Sw->Hs",
+                "Hs->Sw",
+                "Hw->Ss",
+                "Ss<->Hw",
+                "Sw<->Hs",
+                "Ss<->Sw",
+                "Sw<->Ss",
+                "Hs->Sw->Sw",
+                "Hw->Ss->Sw",
+                "Hw->Sw->Ss",
+                "Ss->Hw->Sw",
+                "Sw->Hs->Sw",
+                "Sw->Hw->Ss",
+                "Hs->Sw->Sw->1",
+                "Hw->Ss->Sw->1",
+                "Hw->Sw->Ss->1",
+                "Ss->Hw->Sw->1",
+                "Ss->Hs->Sw->1",
+                "Sw->Hw->Ss->1",
+                "Ss->Hw->Hw->1",
+                "Sw->Hs->Hw->1",
+                "Sw->Hw->Hs->1",
+                "Ss<->Hw<->Hw->1",
+                "Sw<->Hs<->Hw->1",
+                "Sw<->Hw<->Hs->1",
+                "Ss<->Hw<->Sw->1",
+                "Sw<->Hs<->Sw->1",
+                "Sw<->Hw<->Ss->1",
+                "Ss->Hw<->Sw",
+                "Sw->Hs<->Sw",
+                "Sw->Hw<->Ss"
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/native/gtestLauncher.cpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 "prims/jni.h"
+
+extern "C" {
+  JNIIMPORT void JNICALL runUnitTests(int argv, char** argc);
+}
+
+int main(int argc, char** argv) {
+  runUnitTests(argc, argv);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/native/gtestMain.cpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef __APPLE__
+#  include <dlfcn.h>
+#endif
+
+#include "prims/jni.h"
+#include "unittest.hpp"
+
+extern "C" {
+
+static int init_jvm(int argc, char **argv, bool is_executing_death_test) {
+  // don't care about the program name
+  argc--;
+  argv++;
+
+  int extra_jvm_args = is_executing_death_test ? 4 : 2;
+  int num_jvm_options = argc + extra_jvm_args;
+
+  JavaVMOption* options = new JavaVMOption[num_jvm_options];
+  options[0].optionString = (char*) "-Dsun.java.launcher.is_altjvm=true";
+  options[1].optionString = (char*) "-XX:+ExecutingUnitTests";
+
+  if (is_executing_death_test) {
+    // don't create core files or hs_err files when executing death tests
+    options[2].optionString = (char*) "-XX:+SuppressFatalErrorMessage";
+    options[3].optionString = (char*) "-XX:-CreateCoredumpOnCrash";
+  }
+
+  for (int i = 0; i < argc; i++) {
+    options[extra_jvm_args + i].optionString = argv[i];
+  }
+
+  JavaVMInitArgs args;
+  args.version = JNI_VERSION_1_8;
+  args.nOptions = num_jvm_options;
+  args.options = options;
+
+  JavaVM* jvm;
+  JNIEnv* env;
+
+  return JNI_CreateJavaVM(&jvm, (void**)&env, &args);
+}
+
+class JVMInitializerListener : public ::testing::EmptyTestEventListener {
+ private:
+  int _argc;
+  char** _argv;
+  bool _is_initialized;
+
+  void initialize_jvm() {
+  }
+
+ public:
+  JVMInitializerListener(int argc, char** argv) :
+    _argc(argc), _argv(argv), _is_initialized(false) {
+  }
+
+  virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+    const char* name = test_info.name();
+    if (strstr(name, "_test_vm") != NULL && !_is_initialized) {
+      ASSERT_EQ(init_jvm(_argc, _argv, false), 0) << "Could not initialize the JVM";
+      _is_initialized = true;
+    }
+  }
+};
+
+static bool is_prefix(const char* prefix, const char* str) {
+  return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+static char* get_java_home_arg(int argc, char** argv) {
+  for (int i = 0; i < argc; i++) {
+    if (strncmp(argv[i], "-jdk", strlen(argv[i])) == 0) {
+      return argv[i+1];
+    }
+    if (is_prefix("--jdk=", argv[i])) {
+      return argv[i] + strlen("--jdk=");
+    }
+    if (is_prefix("-jdk:", argv[i])) {
+      return argv[i] + strlen("-jdk:");
+    }
+  }
+  return NULL;
+}
+
+static int num_args_to_skip(char* arg) {
+  if (strcmp(arg, "-jdk") == 0) {
+    return 2; // skip the argument after -jdk as well
+  }
+  if (is_prefix("--jdk=", arg)) {
+    return 1;
+  }
+  if (is_prefix("-jdk:", arg)) {
+    return 1;
+  }
+  return 0;
+}
+
+static char** remove_test_runner_arguments(int* argcp, char **argv) {
+  int argc = *argcp;
+  char** new_argv = (char**) malloc(sizeof(char*) * argc);
+  int new_argc = 0;
+
+  int i = 0;
+  while (i < argc) {
+    int args_to_skip = num_args_to_skip(argv[i]);
+    if (args_to_skip == 0) {
+      new_argv[new_argc] = argv[i];
+      i++;
+      new_argc++;
+    } else {
+      i += num_args_to_skip(argv[i]);
+    }
+  }
+
+  *argcp = new_argc;
+  return new_argv;
+}
+
+JNIEXPORT void JNICALL runUnitTests(int argc, char** argv) {
+  // Must look at googletest options before initializing googletest, since
+  // InitGoogleTest removes googletest options from argv.
+  bool is_executing_death_test = true;
+  for (int i = 0; i < argc; i++) {
+    const char* death_test_flag = "--gtest_internal_run_death_test";
+    if (is_prefix(death_test_flag, argv[i])) {
+      is_executing_death_test = true;
+    }
+  }
+
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::GTEST_FLAG(death_test_style) = "threadsafe";
+//  ::testing::GTEST_FLAG(death_test_output_prefix) = "Other VM";
+
+  char* java_home = get_java_home_arg(argc, argv);
+  if (java_home == NULL) {
+    fprintf(stderr, "ERROR: You must specify a JDK to use for running the unit tests.\n");
+    exit(1);
+  }
+#ifndef _WIN32
+  int overwrite = 1; // overwrite an eventual existing value for JAVA_HOME
+  setenv("JAVA_HOME", java_home, overwrite);
+
+// workaround for JDK-7131356
+#ifdef __APPLE__
+  size_t len = strlen(java_home) + strlen("/lib/jli/libjli.dylib") + 1;
+  char* path = new char[len];
+  snprintf(path, len, "%s/lib/jli/libjli.dylib", java_home);
+  dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+#endif // __APPLE__
+
+#else  // _WIN32
+  char* java_home_var = "_ALT_JAVA_HOME_DIR";
+  size_t len = strlen(java_home) + strlen(java_home_var) + 2;
+  char * envString = new char[len];
+  sprintf_s(envString, len, "%s=%s", java_home_var, java_home);
+  _putenv(envString);
+#endif // _WIN32
+  argv = remove_test_runner_arguments(&argc, argv);
+
+  if (is_executing_death_test) {
+    if (init_jvm(argc, argv, true) != 0) {
+      abort();
+    }
+  } else {
+    ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();
+    listeners.Append(new JVMInitializerListener(argc, argv));
+  }
+
+  int result = RUN_ALL_TESTS();
+  if (result != 0) {
+    fprintf(stderr, "ERROR: RUN_ALL_TESTS() failed. Error %d\n", result);
+    exit(2);
+  }
+}
+
+} // extern "C"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/native/runtime/test_os.cpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 "runtime/os.hpp"
+#include "unittest.hpp"
+
+TEST_VM(os, page_size_for_region) {
+  size_t large_page_example = 4 * M;
+  size_t large_page = os::page_size_for_region_aligned(large_page_example, 1);
+
+  size_t small_page = os::vm_page_size();
+  if (large_page > small_page) {
+    size_t num_small_in_large = large_page / small_page;
+    size_t page = os::page_size_for_region_aligned(large_page, num_small_in_large);
+    ASSERT_EQ(page, small_page) << "Did not get a small page";
+  }
+}
+
+#ifdef ASSERT
+TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages, "sanity") {
+  size_t region_size = 16 * os::vm_page_size();
+  os::page_size_for_region_aligned(region_size, 0); // should assert
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/native/unittest.hpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define GTEST_DONT_DEFINE_TEST 1
+#include "gtest/gtest.h"
+#ifdef assert
+  #undef assert
+#endif
+
+#define CONCAT(a, b) a ## b
+
+#define TEST(category, name) GTEST_TEST(category, CONCAT(name, _test))
+
+#define TEST_VM(category, name) GTEST_TEST(category, CONCAT(name, _test_vm))
+
+#define TEST_VM_F(test_fixture, name)                               \
+  GTEST_TEST_(test_fixture, name ## _test_vm, test_fixture,         \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+#define TEST_OTHER_VM(category, name)                               \
+  static void test_  ## category ## _ ## name ## _();               \
+                                                                    \
+  static void child_ ## category ## _ ## name ## _() {              \
+    ::testing::GTEST_FLAG(throw_on_failure) = true;                 \
+    test_ ## category ## _ ## name ## _();                          \
+    fprintf(stderr, "OKIDOKI");                                     \
+    exit(0);                                                        \
+  }                                                                 \
+                                                                    \
+  TEST(category, CONCAT(name, _other_vm)) {                         \
+    ASSERT_EXIT(child_ ## category ## _ ## name ## _(),             \
+                ::testing::ExitedWithCode(0),                       \
+                ".*OKIDOKI.*");                                     \
+  }                                                                 \
+                                                                    \
+  void test_ ## category ## _ ## name ## _()
+
+#ifdef ASSERT
+#define TEST_VM_ASSERT(category, name)                              \
+  static void test_  ## category ## _ ## name ## _();               \
+                                                                    \
+  static void child_ ## category ## _ ## name ## _() {              \
+    ::testing::GTEST_FLAG(throw_on_failure) = true;                 \
+    test_ ## category ## _ ## name ## _();                          \
+    exit(0);                                                        \
+  }                                                                 \
+                                                                    \
+  TEST(category, CONCAT(name, _vm_assert)) {                        \
+    ASSERT_EXIT(child_ ## category ## _ ## name ## _(),             \
+                ::testing::ExitedWithCode(1),                       \
+                "assert failed");                                   \
+  }                                                                 \
+                                                                    \
+  void test_ ## category ## _ ## name ## _()
+#else
+#define TEST_VM_ASSERT(...)                                         \
+    TEST_VM_ASSERT is only available in debug builds
+#endif
+
+#ifdef ASSERT
+#define TEST_VM_ASSERT_MSG(category, name, msg)                     \
+  static void test_  ## category ## _ ## name ## _();               \
+                                                                    \
+  static void child_ ## category ## _ ## name ## _() {              \
+    ::testing::GTEST_FLAG(throw_on_failure) = true;                 \
+    test_ ## category ## _ ## name ## _();                          \
+    exit(0);                                                        \
+  }                                                                 \
+                                                                    \
+  TEST(category, CONCAT(name, _vm_assert)) {                        \
+    ASSERT_EXIT(child_ ## category ## _ ## name ## _(),             \
+                ::testing::ExitedWithCode(1),                       \
+                "assert failed: " msg);                             \
+  }                                                                 \
+                                                                    \
+  void test_ ## category ## _ ## name ## _()
+#else
+#define TEST_VM_ASSERT_MSG(...)                                     \
+    TEST_VM_ASSERT_MSG is only available in debug builds
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/native/utilities/test_quicksort.cpp	Mon May 09 23:53:11 2016 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 "prims/jvm.h"
+#include "utilities/quickSort.hpp"
+#include "unittest.hpp"
+
+static int int_comparator(int a, int b) {
+  if (a == b) {
+    return 0;
+  } else if (a < b) {
+    return -1;
+  }
+
+  // a > b
+  return 1;
+}
+
+TEST(utilities, quicksort) {
+  int test_array[] = {3,2,1};
+  QuickSort::sort(test_array, 3, int_comparator, false);
+
+  ASSERT_EQ(1, test_array[0]);
+  ASSERT_EQ(2, test_array[1]);
+  ASSERT_EQ(3, test_array[2]);
+}