Merge
authorjwilhelm
Mon, 28 Sep 2015 15:05:02 +0200
changeset 33104 a7c0f60a1294
parent 32827 b00f765af244 (current diff)
parent 33103 116b558af514 (diff)
child 33105 294e48b4f704
Merge
--- a/hotspot/make/windows/makefiles/compile.make	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/make/windows/makefiles/compile.make	Mon Sep 28 15:05:02 2015 +0200
@@ -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
@@ -31,6 +31,7 @@
 #   /nologo   Supress copyright message at every cl.exe startup
 #   /W3       Warning level 3
 #   /Zi       Include debugging information
+#   /d2Zi+    Extended debugging symbols for optimized code (/Zo in VS2013 Update 3 and later)
 #   /WX       Treat any warning error as a fatal error
 #   /MD       Use dynamic multi-threaded runtime (msvcrt.dll or msvc*NN.dll)
 #   /MTd      Use static multi-threaded runtime debug versions
@@ -57,7 +58,7 @@
 
 # Let's add debug information when Full Debug Symbols is enabled
 !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
-CXX_FLAGS=$(CXX_FLAGS) /Zi
+CXX_FLAGS=$(CXX_FLAGS) /Zi /d2Zi+
 !endif
 
 # Based on BUILDARCH we add some flags and select the default compiler name
--- a/hotspot/make/windows/makefiles/vm.make	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/make/windows/makefiles/vm.make	Mon Sep 28 15:05:02 2015 +0200
@@ -163,6 +163,7 @@
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc/cms
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc/g1
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/asm
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/logging
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims
@@ -250,6 +251,9 @@
 {$(COMMONSRC)\share\vm\asm}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
+{$(COMMONSRC)\share\vm\logging}.cpp.obj::
+        $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
 {$(COMMONSRC)\share\vm\memory}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
@@ -330,6 +334,9 @@
 {$(ALTSRC)\share\vm\asm}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
+{$(ALTSRC)\share\vm\logging}.cpp.obj::
+        $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
 {$(ALTSRC)\share\vm\memory}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -3063,11 +3063,15 @@
 
   if (UseCondCardMark) {
     Label L_already_dirty;
+    membar(StoreLoad);
     ldrb(rscratch2,  Address(obj, rscratch1));
     cbz(rscratch2, L_already_dirty);
     strb(zr, Address(obj, rscratch1));
     bind(L_already_dirty);
   } else {
+    if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
+      membar(StoreStore);
+    }
     strb(zr, Address(obj, rscratch1));
   }
 }
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -746,6 +746,9 @@
           const Register count = end; // 'end' register contains bytes count now
           __ mov(scratch, (address)ct->byte_map_base);
           __ add(start, start, scratch);
+          if (UseConcMarkSweepGC) {
+            __ membar(__ StoreStore);
+          }
           __ BIND(L_loop);
           __ strb(zr, Address(start, count));
           __ subs(count, count, 1);
--- a/hotspot/src/share/vm/Xusage.txt	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/Xusage.txt	Mon Sep 28 15:05:02 2015 +0200
@@ -7,6 +7,7 @@
     -Xbootclasspath/p:<directories and zip/jar files separated by ;>
                       prepend in front of bootstrap class path
     -Xnoclassgc       disable class garbage collection
+    -Xlog:<opts>      control JVM logging, use -Xlog:help for details
     -Xloggc:<file>    log GC status to a file with time stamps
     -Xbatch           disable background compilation
     -Xms<size>        set initial Java heap size
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -1630,6 +1630,9 @@
     __ move(dirty, card_addr);
     __ branch_destination(L_already_dirty->label());
   } else {
+    if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
+      __ membar_storestore();
+    }
     __ move(dirty, card_addr);
   }
 #endif
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -1235,7 +1235,8 @@
 }
 
 // Helper class to get rid of some boilerplate code.
-class G1CMTraceTime : public GCTraceTime {
+class G1CMTraceTime : public StackObj {
+  GCTraceTimeImpl _gc_trace_time;
   static bool doit_and_prepend(bool doit) {
     if (doit) {
       gclog_or_tty->put(' ');
@@ -1245,7 +1246,7 @@
 
  public:
   G1CMTraceTime(const char* title, bool doit)
-    : GCTraceTime(title, doit_and_prepend(doit), false, G1CollectedHeap::heap()->gc_timer_cm(),
+    : _gc_trace_time(title, doit_and_prepend(doit), false, G1CollectedHeap::heap()->gc_timer_cm(),
         G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id()) {
   }
 };
--- a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -197,7 +197,9 @@
 }
 
 void G1CodeRootSet::allocate_small_table() {
-  _table = new CodeRootSetTable(SmallSize);
+  CodeRootSetTable* temp = new CodeRootSetTable(SmallSize);
+
+  OrderAccess::release_store_ptr(&_table, temp);
 }
 
 void CodeRootSetTable::purge_list_append(CodeRootSetTable* table) {
--- a/hotspot/src/share/vm/gc/shared/gcTraceTime.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTraceTime.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -35,7 +35,7 @@
 #include "utilities/ticks.inline.hpp"
 
 
-GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id) :
+GCTraceTimeImpl::GCTraceTimeImpl(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id) :
     _title(title), _doit(doit), _print_cr(print_cr), _timer(timer), _start_counter() {
   if (_doit || _timer != NULL) {
     _start_counter.stamp();
@@ -59,7 +59,7 @@
   }
 }
 
-GCTraceTime::~GCTraceTime() {
+GCTraceTimeImpl::~GCTraceTimeImpl() {
   Ticks stop_counter;
 
   if (_doit || _timer != NULL) {
--- a/hotspot/src/share/vm/gc/shared/gcTraceTime.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTraceTime.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -26,12 +26,13 @@
 #define SHARE_VM_GC_SHARED_GCTRACETIME_HPP
 
 #include "gc/shared/gcTrace.hpp"
+#include "memory/allocation.hpp"
 #include "prims/jni_md.h"
 #include "utilities/ticks.hpp"
 
 class GCTimer;
 
-class GCTraceTime {
+class GCTraceTimeImpl VALUE_OBJ_CLASS_SPEC {
   const char* _title;
   bool _doit;
   bool _print_cr;
@@ -39,8 +40,16 @@
   Ticks _start_counter;
 
  public:
-  GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id);
-  ~GCTraceTime();
+  GCTraceTimeImpl(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id);
+  ~GCTraceTimeImpl();
+};
+
+class GCTraceTime : public StackObj {
+  GCTraceTimeImpl _gc_trace_time_impl;
+
+ public:
+  GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id) :
+    _gc_trace_time_impl(title, doit, print_cr, timer, gc_id) {};
 };
 
 #endif // SHARE_VM_GC_SHARED_GCTRACETIME_HPP
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -31,6 +31,7 @@
 #include "gc/shared/gcTraceTime.hpp"
 #include "gc/shared/referencePolicy.hpp"
 #include "gc/shared/referenceProcessor.hpp"
+#include "memory/allocation.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/jniHandles.hpp"
@@ -182,6 +183,21 @@
   return total;
 }
 
+static void log_ref_count(size_t count, bool doit) {
+  if (doit) {
+    gclog_or_tty->print(", " SIZE_FORMAT " refs", count);
+  }
+}
+
+class GCRefTraceTime : public StackObj {
+  GCTraceTimeImpl _gc_trace_time;
+ public:
+  GCRefTraceTime(const char* title, bool doit, GCTimer* timer, GCId gc_id, size_t count) :
+    _gc_trace_time(title, doit, false, timer, gc_id) {
+    log_ref_count(count, doit);
+  }
+};
+
 ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
   BoolObjectClosure*           is_alive,
   OopClosure*                  keep_alive,
@@ -206,48 +222,48 @@
 
   bool trace_time = PrintGCDetails && PrintReferenceGC;
 
+  // Include cleaners 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.
+  ReferenceProcessorStats stats(
+      total_count(_discoveredSoftRefs),
+      total_count(_discoveredWeakRefs),
+      total_count(_discoveredFinalRefs),
+      total_count(_discoveredPhantomRefs) + total_count(_discoveredCleanerRefs));
+
   // Soft references
-  size_t soft_count = 0;
   {
-    GCTraceTime tt("SoftReference", trace_time, false, gc_timer, gc_id);
-    soft_count =
-      process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
-                                 is_alive, keep_alive, complete_gc, task_executor);
+    GCRefTraceTime tt("SoftReference", trace_time, gc_timer, gc_id, stats.soft_count());
+    process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
+                               is_alive, keep_alive, complete_gc, task_executor);
   }
 
   update_soft_ref_master_clock();
 
   // Weak references
-  size_t weak_count = 0;
   {
-    GCTraceTime tt("WeakReference", trace_time, false, gc_timer, gc_id);
-    weak_count =
-      process_discovered_reflist(_discoveredWeakRefs, NULL, true,
-                                 is_alive, keep_alive, complete_gc, task_executor);
+    GCRefTraceTime tt("WeakReference", trace_time, gc_timer, gc_id, stats.weak_count());
+    process_discovered_reflist(_discoveredWeakRefs, NULL, true,
+                               is_alive, keep_alive, complete_gc, task_executor);
   }
 
   // Final references
-  size_t final_count = 0;
   {
-    GCTraceTime tt("FinalReference", trace_time, false, gc_timer, gc_id);
-    final_count =
-      process_discovered_reflist(_discoveredFinalRefs, NULL, false,
-                                 is_alive, keep_alive, complete_gc, task_executor);
+    GCRefTraceTime tt("FinalReference", trace_time, gc_timer, gc_id, stats.final_count());
+    process_discovered_reflist(_discoveredFinalRefs, NULL, false,
+                               is_alive, keep_alive, complete_gc, task_executor);
   }
 
   // Phantom references
-  size_t phantom_count = 0;
   {
-    GCTraceTime tt("PhantomReference", trace_time, false, gc_timer, gc_id);
-    phantom_count =
-      process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
-                                 is_alive, keep_alive, complete_gc, task_executor);
+    GCRefTraceTime tt("PhantomReference", trace_time, gc_timer, gc_id, stats.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
+    // Process cleaners, but include them in phantom timing.  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,
+    process_discovered_reflist(_discoveredCleanerRefs, NULL, true,
                                  is_alive, keep_alive, complete_gc, task_executor);
   }
 
@@ -258,13 +274,14 @@
   // resurrect a "post-mortem" object.
   {
     GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer, gc_id);
+    NOT_PRODUCT(log_ref_count(count_jni_refs(), trace_time);)
     if (task_executor != NULL) {
       task_executor->set_single_threaded_mode();
     }
     process_phaseJNI(is_alive, keep_alive, complete_gc);
   }
 
-  return ReferenceProcessorStats(soft_count, weak_count, final_count, phantom_count);
+  return stats;
 }
 
 #ifndef PRODUCT
@@ -294,12 +311,6 @@
 void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
                                           OopClosure*        keep_alive,
                                           VoidClosure*       complete_gc) {
-#ifndef PRODUCT
-  if (PrintGCDetails && PrintReferenceGC) {
-    unsigned int count = count_jni_refs();
-    gclog_or_tty->print(", %u refs", count);
-  }
-#endif
   JNIHandles::weak_oops_do(is_alive, keep_alive);
   complete_gc->do_void();
 }
@@ -826,8 +837,7 @@
   balance_queues(_discoveredCleanerRefs);
 }
 
-size_t
-ReferenceProcessor::process_discovered_reflist(
+void ReferenceProcessor::process_discovered_reflist(
   DiscoveredList               refs_lists[],
   ReferencePolicy*             policy,
   bool                         clear_referent,
@@ -850,12 +860,6 @@
     balance_queues(refs_lists);
   }
 
-  size_t total_list_count = total_count(refs_lists);
-
-  if (PrintReferenceGC && PrintGCDetails) {
-    gclog_or_tty->print(", " SIZE_FORMAT " refs", total_list_count);
-  }
-
   // Phase 1 (soft refs only):
   // . Traverse the list and remove any SoftReferences whose
   //   referents are not alive, but that should be kept alive for
@@ -898,8 +902,6 @@
                      is_alive, keep_alive, complete_gc);
     }
   }
-
-  return total_list_count;
 }
 
 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) {
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -263,13 +263,13 @@
   }
 
   // Process references with a certain reachability level.
-  size_t process_discovered_reflist(DiscoveredList               refs_lists[],
-                                    ReferencePolicy*             policy,
-                                    bool                         clear_referent,
-                                    BoolObjectClosure*           is_alive,
-                                    OopClosure*                  keep_alive,
-                                    VoidClosure*                 complete_gc,
-                                    AbstractRefProcTaskExecutor* task_executor);
+  void process_discovered_reflist(DiscoveredList               refs_lists[],
+                                  ReferencePolicy*             policy,
+                                  bool                         clear_referent,
+                                  BoolObjectClosure*           is_alive,
+                                  OopClosure*                  keep_alive,
+                                  VoidClosure*                 complete_gc,
+                                  AbstractRefProcTaskExecutor* task_executor);
 
   void process_phaseJNI(BoolObjectClosure* is_alive,
                         OopClosure*        keep_alive,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/log.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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_LOGGING_LOG_HPP
+#define SHARE_VM_LOGGING_LOG_HPP
+
+#include "logging/logLevel.hpp"
+#include "logging/logPrefix.hpp"
+#include "logging/logTagSet.hpp"
+#include "logging/logTag.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/ostream.hpp"
+
+//
+// Logging macros
+//
+// Usage:
+//   log_<level>(<comma separated log tags>)(<printf-style log arguments>);
+// e.g.
+//   log_debug(logging)("message %d", i);
+//
+// Note that these macros will not evaluate the arguments unless the logging is enabled.
+//
+#define log_error(...)   (!log_is_enabled(Error, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Error>
+#define log_warning(...) (!log_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Warning>
+#define log_info(...)    (!log_is_enabled(Info, __VA_ARGS__))    ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info>
+#define log_debug(...)   (!log_is_enabled(Debug, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug>
+#define log_trace(...)   (!log_is_enabled(Trace, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace>
+#ifndef PRODUCT
+#define log_develop(...) (!log_is_enabled(Develop, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Develop>
+#else
+#define DUMMY_ARGUMENT_CONSUMER(...)
+#define log_develop(...) DUMMY_ARGUMENT_CONSUMER
+#endif
+
+// Convenience macro to test if the logging is enabled on the specified level for given tags.
+#define log_is_enabled(level, ...) (Log<LOG_TAGS(__VA_ARGS__)>::is_level(LogLevel::level))
+
+//
+// Log class for more advanced logging scenarios.
+// Has printf-style member functions for each log level (trace(), debug(), etc).
+//
+// Also has outputStream compatible API for the different log-levels.
+// The streams are resource allocated when requested and are accessed through
+// calls to <level>_stream() functions (trace_stream(), debug_stream(), etc).
+//
+// Example usage:
+//   LogHandle(logging) log;
+//   if (log.is_debug()) {
+//     ...
+//     log.debug("result = %d", result).trace(" tracing info");
+//     obj->print_on(log.debug_stream());
+//   }
+//
+#define LogHandle(...)  Log<LOG_TAGS(__VA_ARGS__)>
+
+template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,
+          LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
+class Log VALUE_OBJ_CLASS_SPEC {
+ private:
+  static const size_t LogBufferSize = 512;
+ public:
+  // Make sure no more than the maximum number of tags have been given.
+  // The GuardTag allows this to be detected if/when it happens. If the GuardTag
+  // is not __NO_TAG, the number of tags given exceeds the maximum allowed.
+  STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported!
+
+  static bool is_level(LogLevelType level) {
+    return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level);
+  }
+
+  template <LogLevelType Level>
+  ATTRIBUTE_PRINTF(1, 2)
+  static void write(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    vwrite<Level>(fmt, args);
+    va_end(args);
+  };
+
+  template <LogLevelType Level>
+  ATTRIBUTE_PRINTF(1, 0)
+  static void vwrite(const char* fmt, va_list args) {
+    char buf[LogBufferSize];
+    size_t prefix_len = LogPrefix<T0, T1, T2, T3, T4>::prefix(buf, sizeof(buf));
+    int ret = vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args);
+    assert(ret >= 0 && (size_t)ret < sizeof(buf), "Log message too long");
+    puts<Level>(buf);
+  }
+
+  template <LogLevelType Level>
+  static void puts(const char* string) {
+    LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().log(Level, string);
+  }
+
+#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \
+  Log& v##name(const char* fmt, va_list args) { \
+    vwrite<LogLevel::level>(fmt, args); \
+    return *this; \
+  } \
+  Log& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) { \
+    va_list args; \
+    va_start(args, fmt); \
+    vwrite<LogLevel::level>(fmt, args); \
+    va_end(args); \
+    return *this; \
+  } \
+  static bool is_##name() { \
+    return is_level(LogLevel::level); \
+  } \
+  static outputStream* name##_stream() { \
+    return new logStream(write<LogLevel::level>); \
+  }
+  LOG_LEVEL_LIST
+#undef LOG_LEVEL
+};
+
+#endif // SHARE_VM_LOGGING_LOG_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,353 @@
+/*
+ * 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 "logging/log.hpp"
+#include "logging/logConfiguration.hpp"
+#include "logging/logDecorations.hpp"
+#include "logging/logDecorators.hpp"
+#include "logging/logDiagnosticCommand.hpp"
+#include "logging/logFileOutput.hpp"
+#include "logging/logOutput.hpp"
+#include "logging/logTagLevelExpression.hpp"
+#include "logging/logTagSet.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/os.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+LogOutput** LogConfiguration::_outputs = NULL;
+size_t      LogConfiguration::_n_outputs = 0;
+
+void LogConfiguration::post_initialize() {
+  assert(LogConfiguration_lock != NULL, "Lock must be initialized before post-initialization");
+  LogDiagnosticCommand::registerCommand();
+  LogHandle(logging) log;
+  log.info("Log configuration fully initialized.");
+  if (log.is_trace()) {
+    ResourceMark rm;
+    MutexLocker ml(LogConfiguration_lock);
+    describe(log.trace_stream());
+  }
+}
+
+void LogConfiguration::initialize(jlong vm_start_time) {
+  LogFileOutput::set_file_name_parameters(vm_start_time);
+  LogDecorations::set_vm_start_time_millis(vm_start_time);
+
+  assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
+  _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
+  _outputs[0] = LogOutput::Stdout;
+  _outputs[1] = LogOutput::Stderr;
+  _n_outputs = 2;
+}
+
+void LogConfiguration::finalize() {
+  for (size_t i = 2; i < _n_outputs; i++) {
+    delete _outputs[i];
+  }
+  FREE_C_HEAP_ARRAY(LogOutput*, _outputs);
+}
+
+size_t LogConfiguration::find_output(const char* name) {
+  for (size_t i = 0; i < _n_outputs; i++) {
+    if (strcmp(_outputs[i]->name(), name) == 0) {
+      return i;
+    }
+  }
+  return SIZE_MAX;
+}
+
+LogOutput* LogConfiguration::new_output(char* name, const char* options) {
+  const char* type;
+  char* equals_pos = strchr(name, '=');
+  if (equals_pos == NULL) {
+    type = "file";
+  } else {
+    *equals_pos = '\0';
+    type = name;
+    name = equals_pos + 1;
+  }
+
+  LogOutput* output;
+  if (strcmp(type, "file") == 0) {
+    output = new LogFileOutput(name);
+  } else {
+    // unsupported log output type
+    return NULL;
+  }
+
+  bool success = output->initialize(options);
+  if (!success) {
+    delete output;
+    return NULL;
+  }
+  return output;
+}
+
+size_t LogConfiguration::add_output(LogOutput* output) {
+  size_t idx = _n_outputs++;
+  _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
+  _outputs[idx] = output;
+  return idx;
+}
+
+void LogConfiguration::delete_output(size_t idx) {
+  assert(idx > 1 && idx < _n_outputs,
+         err_msg("idx must be in range 1 < idx < _n_outputs, but idx = " SIZE_FORMAT
+                 " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs));
+  LogOutput* output = _outputs[idx];
+  // Swap places with the last output and shrink the array
+  _outputs[idx] = _outputs[--_n_outputs];
+  _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
+  delete output;
+}
+
+void LogConfiguration::configure_output(size_t idx, const LogTagLevelExpression& tag_level_expression, const LogDecorators& decorators) {
+  assert(idx < _n_outputs, err_msg("Invalid index, idx = " SIZE_FORMAT " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs));
+  LogOutput* output = _outputs[idx];
+  output->set_decorators(decorators);
+  output->set_config_string(tag_level_expression.to_string());
+  bool enabled = false;
+  for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
+    LogLevelType level = tag_level_expression.level_for(*ts);
+    if (level != LogLevel::Off) {
+      enabled = true;
+    }
+    ts->update_decorators(decorators);
+    ts->set_output_level(output, level);
+  }
+
+  // If the output is not used by any tagset it should be removed, unless it is stdout/stderr.
+  if (!enabled && idx > 1) {
+    delete_output(idx);
+  }
+}
+
+void LogConfiguration::disable_output(size_t idx) {
+  LogOutput* out = _outputs[idx];
+  LogDecorators empty_decorators;
+  empty_decorators.clear();
+
+  // Remove the output from all tagsets.
+  for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
+    ts->set_output_level(out, LogLevel::Off);
+    ts->update_decorators(empty_decorators);
+  }
+
+  // Delete the output unless stdout/stderr
+  if (out != LogOutput::Stderr && out != LogOutput::Stdout) {
+    delete_output(find_output(out->name()));
+  } else {
+    out->set_config_string("all=off");
+  }
+}
+
+void LogConfiguration::disable_logging() {
+  assert(LogConfiguration_lock == NULL || LogConfiguration_lock->owned_by_self(),
+         "LogConfiguration lock must be held when calling this function");
+  for (size_t i = 0; i < _n_outputs; i++) {
+    disable_output(i);
+  }
+}
+
+bool LogConfiguration::parse_command_line_arguments(const char* opts) {
+  char* copy = os::strdup_check_oom(opts, mtLogging);
+
+  // Split the option string to its colon separated components.
+  char* what = NULL;
+  char* output_str = NULL;
+  char* decorators_str = NULL;
+  char* output_options = NULL;
+
+  what = copy;
+  char* colon = strchr(what, ':');
+  if (colon != NULL) {
+    *colon = '\0';
+    output_str = colon + 1;
+    colon = strchr(output_str, ':');
+    if (colon != NULL) {
+      *colon = '\0';
+      decorators_str = colon + 1;
+      colon = strchr(decorators_str, ':');
+      if (colon != NULL) {
+        *colon = '\0';
+        output_options = colon + 1;
+      }
+    }
+  }
+
+  // Parse each argument
+  char errbuf[512];
+  stringStream ss(errbuf, sizeof(errbuf));
+  bool success = parse_log_arguments(output_str, what, decorators_str, output_options, &ss);
+  if (!success) {
+    errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline.
+    log_error(logging)("%s", errbuf);
+  }
+
+  os::free(copy);
+  return success;
+}
+
+bool LogConfiguration::parse_log_arguments(const char* outputstr,
+                                           const char* what,
+                                           const char* decoratorstr,
+                                           const char* output_options,
+                                           outputStream* errstream) {
+  assert(LogConfiguration_lock == NULL || LogConfiguration_lock->owned_by_self(),
+         "LogConfiguration lock must be held when calling this function");
+  if (outputstr == NULL || strlen(outputstr) == 0) {
+    outputstr = "stdout";
+  }
+
+  size_t idx;
+  if (outputstr[0] == '#') {
+    int ret = sscanf(outputstr+1, SIZE_FORMAT, &idx);
+    if (ret != 1 || idx >= _n_outputs) {
+      errstream->print_cr("Invalid output index '%s'", outputstr);
+      return false;
+    }
+  } else {
+    idx = find_output(outputstr);
+    if (idx == SIZE_MAX) {
+      char* tmp = os::strdup_check_oom(outputstr, mtLogging);
+      LogOutput* output = new_output(tmp, output_options);
+      os::free(tmp);
+      if (output == NULL) {
+        errstream->print("Unable to add output '%s'", outputstr);
+        if (output_options != NULL && strlen(output_options) > 0) {
+          errstream->print(" with options '%s'", output_options);
+        }
+        errstream->cr();
+        return false;
+      }
+      idx = add_output(output);
+    } else if (output_options != NULL && strlen(output_options) > 0) {
+      errstream->print_cr("Output options for existing outputs are ignored.");
+    }
+  }
+
+  LogTagLevelExpression expr;
+  if (!expr.parse(what, errstream)) {
+    return false;
+  }
+
+  LogDecorators decorators;
+  if (!decorators.parse(decoratorstr, errstream)) {
+    return false;
+  }
+
+  configure_output(idx, expr, decorators);
+  return true;
+}
+
+void LogConfiguration::describe(outputStream* out) {
+  assert(LogConfiguration_lock == NULL || LogConfiguration_lock->owned_by_self(),
+         "LogConfiguration lock must be held when calling this function");
+
+  out->print("Available log levels:");
+  for (size_t i = 0; i < LogLevel::Count; i++) {
+    out->print("%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
+  }
+  out->cr();
+
+  out->print("Available log decorators:");
+  for (size_t i = 0; i < LogDecorators::Count; i++) {
+    LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
+    out->print("%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
+  }
+  out->cr();
+
+  out->print("Available log tags:");
+  for (size_t i = 1; i < LogTag::Count; i++) {
+    out->print("%s %s", (i == 1 ? "" : ","), LogTag::name(static_cast<LogTagType>(i)));
+  }
+  out->cr();
+
+  out->print_cr("Log output configuration:");
+  for (size_t i = 0; i < _n_outputs; i++) {
+    out->print("#" SIZE_FORMAT ": %s %s ", i, _outputs[i]->name(), _outputs[i]->config_string());
+    for (size_t d = 0; d < LogDecorators::Count; d++) {
+      LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
+      if (_outputs[i]->decorators().is_decorator(decorator)) {
+        out->print("%s,", LogDecorators::name(decorator));
+      }
+    }
+    out->cr();
+  }
+}
+
+void LogConfiguration::print_command_line_help(FILE* out) {
+  jio_fprintf(out, "-Xlog Usage: -Xlog[:[what][:[output][:[decorators][:output-options]]]]\n"
+              "\t where 'what' is a combination of tags and levels on the form tag1[+tag2...][*][=level][,...]\n"
+              "\t Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.\n\n");
+
+  jio_fprintf(out, "Available log levels:\n");
+  for (size_t i = 0; i < LogLevel::Count; i++) {
+    jio_fprintf(out, "%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
+  }
+
+  jio_fprintf(out, "\n\nAvailable log decorators: \n");
+  for (size_t i = 0; i < LogDecorators::Count; i++) {
+    LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
+    jio_fprintf(out, "%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
+  }
+  jio_fprintf(out, "\n Decorators can also be specified as 'none' for no decoration.\n\n");
+
+  jio_fprintf(out, "Available log tags:\n");
+  for (size_t i = 1; i < LogTag::Count; i++) {
+    jio_fprintf(out, "%s %s", (i == 1 ? "" : ","), LogTag::name(static_cast<LogTagType>(i)));
+  }
+  jio_fprintf(out, "\n Specifying 'all' instead of a tag combination matches all tag combinations.\n\n");
+
+  jio_fprintf(out, "Available log outputs:\n"
+              " stdout, stderr, file=<filename>\n"
+              " Specifying %%p and/or %%t in the filename will expand to the JVM's PID and startup timestamp, respectively.\n\n"
+
+              "Some examples:\n"
+              " -Xlog\n"
+              "\t Log all messages using 'info' level to stdout with 'uptime', 'levels' and 'tags' decorations.\n"
+              "\t (Equivalent to -Xlog:all=info:stdout:uptime,levels,tags).\n\n"
+
+              " -Xlog:gc\n"
+              "\t Log messages tagged with 'gc' tag using 'info' level to stdout, with default decorations.\n\n"
+
+              " -Xlog:gc=debug:file=gc.txt:none\n"
+              "\t Log messages tagged with 'gc' tag using 'debug' level to file 'gc.txt' with no decorations.\n\n"
+
+              " -Xlog:gc=trace:file=gctrace.txt:uptimemillis,pids:filecount=5,filesize=1024\n"
+              "\t Log messages tagged with 'gc' tag using 'trace' level to a rotating fileset of 5 files of size 1MB,\n"
+              "\t using the base name 'gctrace.txt', with 'uptimemillis' and 'pid' decorations.\n\n"
+
+              " -Xlog:gc::uptime,tid\n"
+              "\t Log messages tagged with 'gc' tag using 'info' level to output 'stdout', using 'uptime' and 'tid' decorations.\n\n"
+
+              " -Xlog:gc*=info,rt*=off\n"
+              "\t Log messages tagged with at least 'gc' using 'info' level, but turn off logging of messages tagged with 'rt'.\n"
+              "\t (Messages tagged with both 'gc' and 'rt' will not be logged.)\n\n"
+
+              " -Xlog:disable -Xlog:rt=trace:rttrace.txt\n"
+              "\t Turn off all logging, including warnings and errors,\n"
+              "\t and then enable messages tagged with 'rt' using 'trace' level to file 'rttrace.txt'.\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logConfiguration.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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_LOGGING_LOGCONFIGURATION_HPP
+#define SHARE_VM_LOGGING_LOGCONFIGURATION_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogOutput;
+class LogDecorators;
+class LogTagLevelExpression;
+
+// Global configuration of logging. Handles parsing and configuration of the logging framework,
+// and manages the list of configured log outputs. The actual tag and level configuration is
+// kept implicitly in the LogTagSets and their LogOutputLists. During configuration the tagsets
+// are iterated over and updated accordingly.
+class LogConfiguration : public AllStatic {
+ private:
+  static LogOutput**  _outputs;
+  static size_t       _n_outputs;
+
+  // Create a new output. Returns NULL if failed.
+  static LogOutput* new_output(char* name, const char* options = NULL);
+
+  // Add an output to the list of configured outputs. Returns the assigned index.
+  static size_t add_output(LogOutput* out);
+
+  // Delete a configured output. The stderr/stdout outputs can not be removed.
+  // Output should be completely disabled before it is deleted.
+  static void delete_output(size_t idx);
+
+  // Disable all logging to the specified output and then delete it (unless it is stdout/stderr).
+  static void disable_output(size_t idx);
+
+  // Get output index by name. Returns SIZE_MAX if output not found.
+  static size_t find_output(const char* name);
+
+  // Configure output (add or update existing configuration) to log on tag-level combination using specified decorators.
+  static void configure_output(size_t idx, const LogTagLevelExpression& tag_level_expression, const LogDecorators& decorators);
+
+ public:
+  // Initialization and finalization of log configuration, to be run at vm startup and shutdown respectively.
+  static void initialize(jlong vm_start_time);
+  static void finalize();
+
+  // Perform necessary post-initialization after VM startup. Enables reconfiguration of logging.
+  static void post_initialize();
+
+  // Disable all logging, equivalent to -Xlog:disable.
+  static void disable_logging();
+
+  // Parse command line configuration. Parameter 'opts' is the string immediately following the -Xlog: argument ("gc" for -Xlog:gc).
+  static bool parse_command_line_arguments(const char* opts = "all");
+
+  // Parse separated configuration arguments (from JCmd/MBean and command line).
+  static bool parse_log_arguments(const char* outputstr,
+                                  const char* what,
+                                  const char* decoratorstr,
+                                  const char* output_options,
+                                  outputStream* errstream);
+
+  // Prints log configuration to outputStream, used by JCmd/MBean.
+  static void describe(outputStream* out);
+
+  // Prints usage help for command line log configuration.
+  static void print_command_line_help(FILE* out);
+};
+
+#endif // SHARE_VM_LOGGING_LOGCONFIGURATION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDecorations.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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 "logging/logConfiguration.hpp"
+#include "logging/logDecorations.hpp"
+#include "runtime/os.inline.hpp"
+#include "runtime/thread.inline.hpp"
+#include "services/management.hpp"
+
+jlong LogDecorations::_vm_start_time_millis = 0;
+
+LogDecorations::LogDecorations(LogLevelType level, const LogTagSet &tagset, const LogDecorators &decorators)
+  : _level(level), _tagset(tagset), _millis(-1) {
+  create_decorations(decorators);
+}
+
+void LogDecorations::create_decorations(const LogDecorators &decorators) {
+  char* position = _decorations_buffer;
+  #define DECORATOR(full_name, abbr) \
+  if (decorators.is_decorator(LogDecorators::full_name##_decorator)) { \
+    _decoration_offset[LogDecorators::full_name##_decorator] = position; \
+    position = create_##full_name##_decoration(position) + 1; \
+  }
+  DECORATOR_LIST
+#undef DECORATOR
+}
+
+jlong LogDecorations::java_millis() {
+  if (_millis < 0) {
+    _millis = os::javaTimeMillis();
+  }
+  return _millis;
+}
+
+#define ASSERT_AND_RETURN(written, pos) \
+    assert(written >= 0, "Decorations buffer overflow"); \
+    return pos + written;
+
+char* LogDecorations::create_time_decoration(char* pos) {
+  char* buf = os::iso8601_time(pos, 29);
+  int written = buf == NULL ? -1 : 29;
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_uptime_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%.3fs", os::elapsedTime());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_timemillis_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), INT64_FORMAT "ms", java_millis());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_uptimemillis_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer),
+                             INT64_FORMAT "ms", java_millis() - _vm_start_time_millis);
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_timenanos_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), INT64_FORMAT "ns", os::javaTimeNanos());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_uptimenanos_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), INT64_FORMAT "ns", os::elapsed_counter());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_pid_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%d", os::current_process_id());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char * LogDecorations::create_tid_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer),
+                             INTX_FORMAT, Thread::current()->osthread()->thread_id());
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char* LogDecorations::create_level_decoration(char* pos) {
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%s", LogLevel::name(_level));
+  ASSERT_AND_RETURN(written, pos)
+}
+
+char* LogDecorations::create_tags_decoration(char* pos) {
+  int written = _tagset.label(pos, DecorationsBufferSize - (pos - _decorations_buffer));
+  ASSERT_AND_RETURN(written, pos)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDecorations.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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_LOGGING_LOGDECORATIONS_HPP
+#define SHARE_VM_LOGGING_LOGDECORATIONS_HPP
+
+#include "logging/logDecorators.hpp"
+#include "logging/logTagSet.hpp"
+#include "memory/allocation.hpp"
+
+// Temporary object containing the necessary data for a log call's decorations (timestamps, etc).
+class LogDecorations VALUE_OBJ_CLASS_SPEC {
+ public:
+  static const int DecorationsBufferSize = 256;
+ private:
+  char _decorations_buffer[DecorationsBufferSize];
+  char* _decoration_offset[LogDecorators::Count];
+  LogLevelType _level;
+  LogTagSet _tagset;
+  jlong _millis;
+  static jlong _vm_start_time_millis;
+
+  jlong java_millis();
+  void create_decorations(const LogDecorators& decorators);
+
+#define DECORATOR(name, abbr) char* create_##name##_decoration(char* pos);
+  DECORATOR_LIST
+#undef DECORATOR
+
+ public:
+  LogDecorations(LogLevelType level, const LogTagSet& tagset, const LogDecorators& decorators);
+
+  const char* decoration(LogDecorators::Decorator decorator) const {
+    return _decoration_offset[decorator];
+  }
+
+  static void set_vm_start_time_millis(jlong start_time) {
+    _vm_start_time_millis = start_time;
+  }
+};
+
+#endif // SHARE_VM_LOGGING_LOGDECORATIONS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDecorators.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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 "logging/logDecorators.hpp"
+#include "runtime/os.inline.hpp"
+
+const char* LogDecorators::_name[][2] = {
+#define DECORATOR(n, a) {#n, #a},
+  DECORATOR_LIST
+#undef DECORATOR
+};
+
+LogDecorators::Decorator LogDecorators::from_string(const char* str) {
+  for (size_t i = 0; i < Count; i++) {
+    Decorator d = static_cast<Decorator>(i);
+    if (strcasecmp(str, name(d)) == 0 || strcasecmp(str, abbreviation(d)) == 0) {
+      return d;
+    }
+  }
+  return Invalid;
+}
+
+bool LogDecorators::parse(const char* decorator_args, outputStream* errstream) {
+  if (decorator_args == NULL || strlen(decorator_args) == 0) {
+    _decorators = DefaultDecoratorsMask;
+    return true;
+  }
+
+  if (strcasecmp(decorator_args, "none") == 0 ) {
+    _decorators = 0;
+    return true;
+  }
+
+  bool result = true;
+  uint tmp_decorators = 0;
+  char* args_copy = os::strdup_check_oom(decorator_args, mtLogging);
+  char* token = args_copy;
+  char* comma_pos;
+  do {
+    comma_pos = strchr(token, ',');
+    if (comma_pos != NULL) {
+      *comma_pos = '\0';
+    }
+    Decorator d = from_string(token);
+    if (d == Invalid) {
+      if (errstream != NULL) {
+        errstream->print_cr("Invalid decorator '%s'.", token);
+      }
+      result = false;
+      break;
+    }
+    tmp_decorators |= mask(d);
+    token = comma_pos + 1;
+  } while (comma_pos != NULL);
+  os::free(args_copy);
+  if (result) {
+    _decorators = tmp_decorators;
+  }
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDecorators.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,105 @@
+/*
+ * 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_LOGGING_LOGDECORATORS_HPP
+#define SHARE_VM_LOGGING_LOGDECORATORS_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// The list of available decorators:
+// time         - Current time and date in ISO-8601 format
+// uptime       - Time since the start of the JVM in seconds and milliseconds (e.g., 6.567s)
+// timemillis   - The same value as generated by System.currentTimeMillis()
+// uptimemillis - Milliseconds since the JVM started
+// timenanos    - The same value as generated by System.nanoTime()
+// uptimenanos  - Nanoseconds since the JVM started
+// pid          - The process identifier
+// tid          - The thread identifier
+// level        - The level associated with the log message
+// tags         - The tag-set associated with the log message
+#define DECORATOR_LIST          \
+  DECORATOR(time,         t)    \
+  DECORATOR(uptime,       u)    \
+  DECORATOR(timemillis,   tm)   \
+  DECORATOR(uptimemillis, um)   \
+  DECORATOR(timenanos,    tn)   \
+  DECORATOR(uptimenanos,  un)   \
+  DECORATOR(pid,          p)    \
+  DECORATOR(tid,          ti)   \
+  DECORATOR(level,        l)    \
+  DECORATOR(tags,         tg)
+
+// LogDecorators represents a selection of decorators that should be prepended to
+// each log message for a given output. Decorators are always prepended in the order
+// declared above. For example, logging with 'uptime, level, tags' decorators results in:
+// [0,943s][info   ][logging] message.
+class LogDecorators VALUE_OBJ_CLASS_SPEC {
+ public:
+  enum Decorator {
+#define DECORATOR(name, abbr) name##_decorator,
+    DECORATOR_LIST
+#undef DECORATOR
+    Count,
+    Invalid
+  };
+
+ private:
+  uint _decorators;
+  static const char* _name[][2];
+  static const uint DefaultDecoratorsMask = (1 << uptime_decorator) | (1 << level_decorator) | (1 << tags_decorator);
+
+  static uint mask(LogDecorators::Decorator decorator) {
+    return 1 << decorator;
+  }
+
+ public:
+  LogDecorators() : _decorators(DefaultDecoratorsMask) {
+  };
+
+  void clear() {
+    _decorators = 0;
+  }
+
+  static const char* name(LogDecorators::Decorator decorator) {
+    return _name[decorator][0];
+  }
+
+  static const char* abbreviation(LogDecorators::Decorator decorator) {
+    return _name[decorator][1];
+  }
+
+  static LogDecorators::Decorator from_string(const char* str);
+
+  void combine_with(const LogDecorators &source) {
+    _decorators |= source._decorators;
+  }
+
+  bool is_decorator(LogDecorators::Decorator decorator) const {
+    return (_decorators & mask(decorator)) != 0;
+  }
+
+  bool parse(const char* decorator_args, outputStream* errstream = NULL);
+};
+
+#endif // SHARE_VM_LOGGING_LOGDECORATORS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDiagnosticCommand.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,94 @@
+/*
+ * 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 "logging/logConfiguration.hpp"
+#include "logging/logDiagnosticCommand.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+LogDiagnosticCommand::LogDiagnosticCommand(outputStream* output, bool heap_allocated)
+  : DCmdWithParser(output, heap_allocated),
+    _output("output", "The name or index (#<index>) of output to configure.", "STRING", false),
+    _output_options("output_options", "Options for the output.", "STRING", false),
+    _what("what", "Configures what tags to log.", "STRING", false),
+    _decorators("decorators", "Configures which decorators to use. Use 'none' or an empty value to remove all.", "STRING", false),
+    _disable("disable", "Turns off all logging and clears the log configuration.", "BOOLEAN", false),
+    _list("list", "Lists current log configuration.", "BOOLEAN", false) {
+  _dcmdparser.add_dcmd_option(&_output);
+  _dcmdparser.add_dcmd_option(&_output_options);
+  _dcmdparser.add_dcmd_option(&_what);
+  _dcmdparser.add_dcmd_option(&_decorators);
+  _dcmdparser.add_dcmd_option(&_disable);
+  _dcmdparser.add_dcmd_option(&_list);
+}
+
+int LogDiagnosticCommand::num_arguments() {
+  ResourceMark rm;
+  LogDiagnosticCommand* dcmd = new LogDiagnosticCommand(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+
+void LogDiagnosticCommand::registerCommand() {
+  uint32_t full_visibility = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<LogDiagnosticCommand>(full_visibility, true, false));
+}
+
+void LogDiagnosticCommand::execute(DCmdSource source, TRAPS) {
+  bool any_command = false;
+  if (_disable.has_value()) {
+    MutexLocker ml(LogConfiguration_lock);
+    LogConfiguration::disable_logging();
+    any_command = true;
+  }
+
+  if (_output.has_value() || _what.has_value() || _decorators.has_value()) {
+    MutexLocker ml(LogConfiguration_lock);
+    if (!LogConfiguration::parse_log_arguments(_output.value(),
+                                               _what.value(),
+                                               _decorators.value(),
+                                               _output_options.value(),
+                                               output())) {
+      return;
+    }
+    any_command = true;
+  }
+
+  if (_list.has_value()) {
+    MutexLocker ml(LogConfiguration_lock);
+    LogConfiguration::describe(output());
+    any_command = true;
+  }
+
+  if (!any_command) {
+    // If no argument was provided, print usage
+    print_help(LogDiagnosticCommand::name());
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logDiagnosticCommand.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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_LOGGING_LOGDIAGNOSTICCOMMAND_HPP
+#define SHARE_VM_LOGGING_LOGDIAGNOSTICCOMMAND_HPP
+
+#include "services/diagnosticCommand.hpp"
+
+// The LogDiagnosticCommand represents the 'VM.log' DCMD
+// that allows configuration of the logging at runtime.
+// It can be used to view or modify the current log configuration.
+// VM.log without additional arguments prints the usage description.
+// The 'list' argument will list all available log tags,
+// levels, decorators and currently configured log outputs.
+// Specifying 'disable' will disable logging completely.
+// The remaining arguments are used to set a log output to log everything
+// with the specified tags and levels using the given decorators.
+class LogDiagnosticCommand : public DCmdWithParser {
+ protected:
+  DCmdArgument<char *> _output;
+  DCmdArgument<char *> _output_options;
+  DCmdArgument<char *> _what;
+  DCmdArgument<char *> _decorators;
+  DCmdArgument<bool> _disable;
+  DCmdArgument<bool> _list;
+
+ public:
+  LogDiagnosticCommand(outputStream* output, bool heap_allocated);
+  void execute(DCmdSource source, TRAPS);
+  static void registerCommand();
+  static int num_arguments();
+
+  static const char* name() {
+    return "VM.log";
+  }
+
+  static const char* description() {
+    return "Lists, enables, disables or changes a log output configuration.";
+  }
+
+  // Used by SecurityManager. This DCMD requires ManagementPermission = control.
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission", "control", NULL};
+    return p;
+  }
+};
+
+#endif // SHARE_VM_LOGGING_LOGDIAGNOSTICCOMMAND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logFileOutput.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,283 @@
+/*
+ * 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 "logging/log.hpp"
+#include "logging/logConfiguration.hpp"
+#include "logging/logFileOutput.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/os.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/defaultStream.hpp"
+
+const char* LogFileOutput::FileOpenMode = "a";
+const char* LogFileOutput::PidFilenamePlaceholder = "%p";
+const char* LogFileOutput::TimestampFilenamePlaceholder = "%t";
+const char* LogFileOutput::TimestampFormat = "%Y-%m-%d_%H-%M-%S";
+const char* LogFileOutput::FileSizeOptionKey = "filesize";
+const char* LogFileOutput::FileCountOptionKey = "filecount";
+char        LogFileOutput::_pid_str[PidBufferSize];
+char        LogFileOutput::_vm_start_time_str[StartTimeBufferSize];
+
+LogFileOutput::LogFileOutput(const char* name)
+    : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)),
+      _file_name(NULL), _archive_name(NULL), _archive_name_len(0), _current_size(0),
+      _rotate_size(0), _current_file(1), _file_count(0),
+      _rotation_lock(Mutex::leaf, "LogFileOutput rotation lock", true, Mutex::_safepoint_check_sometimes) {
+  _file_name = make_file_name(name, _pid_str, _vm_start_time_str);
+}
+
+void LogFileOutput::set_file_name_parameters(jlong vm_start_time) {
+  int res = jio_snprintf(_pid_str, sizeof(_pid_str), "%d", os::current_process_id());
+  assert(res > 0, "PID buffer too small");
+
+  struct tm local_time;
+  time_t utc_time = vm_start_time / 1000;
+  os::localtime_pd(&utc_time, &local_time);
+  res = (int)strftime(_vm_start_time_str, sizeof(_vm_start_time_str), TimestampFormat, &local_time);
+  assert(res > 0, "VM start time buffer too small.");
+}
+
+LogFileOutput::~LogFileOutput() {
+  if (_stream != NULL) {
+    if (_archive_name != NULL) {
+      archive();
+    }
+    if (fclose(_stream) != 0) {
+      jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n",
+                  _file_name, strerror(errno));
+    }
+  }
+  os::free(_archive_name);
+  os::free(_file_name);
+  os::free(const_cast<char*>(_name));
+}
+
+size_t LogFileOutput::parse_value(const char* value_str) {
+  char* end;
+  unsigned long long value = strtoull(value_str, &end, 10);
+  if (!isdigit(*value_str) || end != value_str + strlen(value_str) || value >= SIZE_MAX) {
+    return SIZE_MAX;
+  }
+  return value;
+}
+
+bool LogFileOutput::configure_rotation(const char* options) {
+  if (options == NULL || strlen(options) == 0) {
+    return true;
+  }
+  bool success = true;
+  char* opts = os::strdup_check_oom(options, mtLogging);
+
+  char* comma_pos;
+  char* pos = opts;
+  do {
+    comma_pos = strchr(pos, ',');
+    if (comma_pos != NULL) {
+      *comma_pos = '\0';
+    }
+
+    char* equals_pos = strchr(pos, '=');
+    if (equals_pos == NULL) {
+      success = false;
+      break;
+    }
+    char* key = pos;
+    char* value_str = equals_pos + 1;
+    *equals_pos = '\0';
+
+    if (strcmp(FileCountOptionKey, key) == 0) {
+      size_t value = parse_value(value_str);
+      if (value == SIZE_MAX || value >= UINT_MAX) {
+        success = false;
+        break;
+      }
+      _file_count = static_cast<uint>(value);
+      _file_count_max_digits = static_cast<uint>(log10(static_cast<double>(_file_count)) + 1);
+      _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits;
+      _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging);
+    } else if (strcmp(FileSizeOptionKey, key) == 0) {
+      size_t value = parse_value(value_str);
+      if (value == SIZE_MAX || value > SIZE_MAX / K) {
+        success = false;
+        break;
+      }
+      _rotate_size = value * K;
+    } else {
+      success = false;
+      break;
+    }
+    pos = comma_pos + 1;
+  } while (comma_pos != NULL);
+
+  os::free(opts);
+  return success;
+}
+
+bool LogFileOutput::initialize(const char* options) {
+  if (!configure_rotation(options)) {
+    return false;
+  }
+  _stream = fopen(_file_name, FileOpenMode);
+  if (_stream == NULL) {
+    log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, strerror(errno));
+    return false;
+  }
+  return true;
+}
+
+int LogFileOutput::write(const LogDecorations& decorations, const char* msg) {
+  if (_stream == NULL) {
+    // An error has occurred with this output, avoid writing to it.
+    return 0;
+  }
+  int written = LogFileStreamOutput::write(decorations, msg);
+  _current_size += written;
+
+  if (should_rotate()) {
+    MutexLockerEx ml(&_rotation_lock, true /* no safepoint check */);
+    if (should_rotate()) {
+      rotate();
+    }
+  }
+
+  return written;
+}
+
+void LogFileOutput::archive() {
+  assert(_archive_name != NULL && _archive_name_len > 0, "Rotation must be configured before using this function.");
+  int ret = jio_snprintf(_archive_name, _archive_name_len, "%s.%0*u",
+                         _file_name, _file_count_max_digits, _current_file);
+  assert(ret >= 0, "Buffer should always be large enough");
+
+  // Attempt to remove possibly existing archived log file before we rename.
+  // Don't care if it fails, we really only care about the rename that follows.
+  remove(_archive_name);
+
+  // Rename the file from ex hotspot.log to hotspot.log.2
+  if (rename(_file_name, _archive_name) == -1) {
+    jio_fprintf(defaultStream::error_stream(), "Could not rename log file '%s' to '%s' (%s).\n",
+                _file_name, _archive_name, strerror(errno));
+  }
+}
+
+void LogFileOutput::rotate() {
+  // Archive the current log file
+  archive();
+
+  // Open the active log file using the same stream as before
+  _stream = freopen(_file_name, FileOpenMode, _stream);
+  if (_stream == NULL) {
+    jio_fprintf(defaultStream::error_stream(), "Could not reopen file '%s' during log rotation (%s).\n",
+                _file_name, strerror(errno));
+    return;
+  }
+
+  // Reset accumulated size, increase current file counter, and check for file count wrap-around.
+  _current_size = 0;
+  _current_file = (_current_file >= _file_count ? 1 : _current_file + 1);
+}
+
+char* LogFileOutput::make_file_name(const char* file_name,
+                                    const char* pid_string,
+                                    const char* timestamp_string) {
+  char* result = NULL;
+
+  // Lets start finding out if we have any %d and/or %t in the name.
+  // We will only replace the first occurrence of any placeholder
+  const char* pid = strstr(file_name, PidFilenamePlaceholder);
+  const char* timestamp = strstr(file_name, TimestampFilenamePlaceholder);
+
+  if (pid == NULL && timestamp == NULL) {
+    // We found no place-holders, return the simple filename
+    return os::strdup_check_oom(file_name, mtLogging);
+  }
+
+  // At least one of the place-holders were found in the file_name
+  const char* first = "";
+  size_t first_pos = -1;
+  size_t first_replace_len = 0;
+
+  const char* second = "";
+  size_t second_pos = -1;
+  size_t second_replace_len = 0;
+
+  // If we found a %p, then setup our variables accordingly
+  if (pid != NULL) {
+    if (timestamp == NULL || pid < timestamp) {
+      first = pid_string;
+      first_pos = pid - file_name;
+      first_replace_len = strlen(PidFilenamePlaceholder);
+    } else {
+      second = pid_string;
+      second_pos = pid - file_name;
+      second_replace_len = strlen(PidFilenamePlaceholder);
+    }
+  }
+
+  if (timestamp != NULL) {
+    if (pid == NULL || timestamp < pid) {
+      first = timestamp_string;
+      first_pos = timestamp - file_name;
+      first_replace_len = strlen(TimestampFilenamePlaceholder);
+    } else {
+      second = timestamp_string;
+      second_pos = timestamp - file_name;
+      second_replace_len = strlen(TimestampFilenamePlaceholder);
+    }
+  }
+
+  size_t first_len = strlen(first);
+  size_t second_len = strlen(second);
+
+  // Allocate the new buffer, size it to hold all we want to put in there +1.
+  size_t result_len =  strlen(file_name) + first_len - first_replace_len + second_len - second_replace_len;
+  result = NEW_C_HEAP_ARRAY(char, result_len + 1, mtLogging);
+
+  // Assemble the strings
+  size_t file_name_pos = 0;
+  size_t i = 0;
+  while (i < result_len) {
+    if (file_name_pos == first_pos) {
+      // We are in the range of the first placeholder
+      strcpy(result + i, first);
+      // Bump output buffer position with length of replacing string
+      i += first_len;
+      // Bump source buffer position to skip placeholder
+      file_name_pos += first_replace_len;
+    } else if (file_name_pos == second_pos) {
+      // We are in the range of the second placeholder
+      strcpy(result + i, second);
+      i += second_len;
+      file_name_pos += second_replace_len;
+    } else {
+      // Else, copy char by char of the original file
+      result[i] = file_name[file_name_pos++];
+      i++;
+    }
+  }
+  // Add terminating char
+  result[result_len] = '\0';
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logFileOutput.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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_LOGGING_LOGFILEOUTPUT_HPP
+#define SHARE_VM_LOGGING_LOGFILEOUTPUT_HPP
+
+#include "logging/logFileStreamOutput.hpp"
+#include "runtime/mutex.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogDecorations;
+
+// The log file output, with support for file rotation based on a target size.
+class LogFileOutput : public LogFileStreamOutput {
+ private:
+  static const char*  FileOpenMode;
+  static const char*  FileCountOptionKey;
+  static const char*  FileSizeOptionKey;
+  static const char*  PidFilenamePlaceholder;
+  static const char*  TimestampFilenamePlaceholder;
+  static const char*  TimestampFormat;
+  static const size_t StartTimeBufferSize = 20;
+  static const size_t PidBufferSize       = 21;
+  static char         _pid_str[PidBufferSize];
+  static char         _vm_start_time_str[StartTimeBufferSize];
+
+  Mutex _rotation_lock;
+  const char* _name;
+  char* _file_name;
+  char* _archive_name;
+
+  uint  _current_file;
+  uint  _file_count;
+  uint  _file_count_max_digits;
+
+  size_t  _archive_name_len;
+  size_t  _rotate_size;
+  size_t  _current_size;
+
+  void archive();
+  void rotate();
+  bool configure_rotation(const char* options);
+  char *make_file_name(const char* file_name, const char* pid_string, const char* timestamp_string);
+  static size_t parse_value(const char* value_str);
+
+  bool should_rotate() const {
+    return _file_count > 0 && _rotate_size > 0 && _current_size >= _rotate_size;
+  }
+
+ public:
+  LogFileOutput(const char *name);
+  virtual ~LogFileOutput();
+  virtual bool initialize(const char* options);
+  virtual int write(const LogDecorations& decorations, const char* msg);
+
+  virtual const char* name() const {
+    return _name;
+  }
+
+  static void set_file_name_parameters(jlong start_time);
+};
+
+#endif // SHARE_VM_LOGGING_LOGFILEOUTPUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logFileStreamOutput.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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 "logging/logDecorators.hpp"
+#include "logging/logDecorations.hpp"
+#include "logging/logFileStreamOutput.hpp"
+#include "memory/allocation.inline.hpp"
+
+LogStdoutOutput LogStdoutOutput::_instance;
+LogStderrOutput LogStderrOutput::_instance;
+
+int LogFileStreamOutput::write(const LogDecorations& decorations, const char* msg) {
+  char decoration_buf[LogDecorations::DecorationsBufferSize];
+  char* position = decoration_buf;
+  int total_written = 0;
+
+  for (uint i = 0; i < LogDecorators::Count; i++) {
+    LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(i);
+    if (!_decorators.is_decorator(decorator)) {
+      continue;
+    }
+    int written = jio_snprintf(position, sizeof(decoration_buf) - total_written, "[%-*s]",
+                               _decorator_padding[decorator],
+                               decorations.decoration(decorator));
+    if (written <= 0) {
+      return -1;
+    } else if (static_cast<size_t>(written - 2) > _decorator_padding[decorator]) {
+      _decorator_padding[decorator] = written - 2;
+    }
+    position += written;
+    total_written += written;
+  }
+
+  if (total_written == 0) {
+    total_written = jio_fprintf(_stream, "%s\n", msg);
+  } else {
+    total_written = jio_fprintf(_stream, "%s %s\n", decoration_buf, msg);
+  }
+  fflush(_stream);
+  return total_written;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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_LOGGING_LOGFILESTREAMOUTPUT_HPP
+#define SHARE_VM_LOGGING_LOGFILESTREAMOUTPUT_HPP
+
+#include "logging/logDecorators.hpp"
+#include "logging/logOutput.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogDecorations;
+
+// Base class for all FileStream-based log outputs.
+class LogFileStreamOutput : public LogOutput {
+ protected:
+  FILE*               _stream;
+  size_t              _decorator_padding[LogDecorators::Count];
+
+  LogFileStreamOutput(FILE *stream) : _stream(stream) {
+    for (size_t i = 0; i < LogDecorators::Count; i++) {
+      _decorator_padding[i] = 0;
+    }
+    _decorator_padding[LogDecorators::level_decorator] = 7;
+  }
+
+ public:
+  virtual int write(const LogDecorations &decorations, const char* msg);
+};
+
+class LogStdoutOutput : public LogFileStreamOutput {
+  friend class LogOutput;
+ private:
+  static LogStdoutOutput _instance;
+  LogStdoutOutput() : LogFileStreamOutput(stdout) {
+    set_config_string("all=off");
+  }
+  virtual bool initialize(const char* options) {
+    return false;
+  }
+ public:
+  virtual const char* name() const {
+    return "stdout";
+  }
+};
+
+class LogStderrOutput : public LogFileStreamOutput {
+  friend class LogOutput;
+ private:
+  static LogStderrOutput _instance;
+  LogStderrOutput() : LogFileStreamOutput(stderr) {
+    set_config_string("all=warning");
+  }
+  virtual bool initialize(const char* options) {
+    return false;
+  }
+ public:
+  virtual const char* name() const {
+    return "stderr";
+  }
+};
+
+#endif // SHARE_VM_LOGGING_LOGFILESTREAMOUTPUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logLevel.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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 "logging/logLevel.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+const char* LogLevel::_name[] = {
+  "off",
+#define LOG_LEVEL(name, printname) #printname,
+  LOG_LEVEL_LIST
+#undef LOG_LEVEL
+};
+
+LogLevelType LogLevel::from_string(const char* str) {
+  for (uint i = 0; i < Count; i++) {
+    if (strcasecmp(str, _name[i]) == 0) {
+      return static_cast<LogLevelType>(i);
+    }
+  }
+  return Invalid;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logLevel.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -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.
+ *
+ */
+#ifndef SHARE_VM_LOGGING_LOGLEVEL_HPP
+#define SHARE_VM_LOGGING_LOGLEVEL_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/macros.hpp"
+
+// The list of log levels:
+//
+//  develop - A non-product level that is finer than trace.
+//            Should be used for really expensive and/or
+//            extensive logging, or logging that shouldn't
+//            or can't be included in a product build.
+//
+//  trace   - Finest level of logging in product builds.
+//            Use for extensive/noisy logging that can
+//            give slow-down when enabled.
+//
+//  debug   - A finer level of logging. Use for semi-noisy
+//            logging that is does not fit the info level.
+//
+//  info    - General level of logging. Use for significant
+//            events and/or informative summaries.
+//
+//  warning - Important messages that are not strictly errors.
+//
+//  error   - Critical messages caused by errors.
+//
+#define LOG_LEVEL_LIST \
+  NOT_PRODUCT(LOG_LEVEL(Develop, develop)) \
+  LOG_LEVEL(Trace, trace) \
+  LOG_LEVEL(Debug, debug) \
+  LOG_LEVEL(Info, info) \
+  LOG_LEVEL(Warning, warning) \
+  LOG_LEVEL(Error, error)
+
+class LogLevel : public AllStatic {
+ public:
+  enum type {
+    Off,
+#define LOG_LEVEL(name, printname) name,
+    LOG_LEVEL_LIST
+#undef LOG_LEVEL
+    Count,
+    Invalid,
+    First = Off + 1,
+    Last = Error,
+    Default = Warning,
+    Unspecified = Info
+  };
+
+  static const char *name(LogLevel::type level) {
+    return _name[level];
+  }
+
+  static LogLevel::type from_string(const char* str);
+
+ private:
+  static const char* _name[];
+};
+
+typedef LogLevel::type LogLevelType;
+
+#endif // SHARE_VM_LOGGING_LOGLEVEL_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logOutput.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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 "logging/logFileStreamOutput.hpp"
+#include "logging/logOutput.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.inline.hpp"
+
+LogOutput* const LogOutput::Stdout = &LogStdoutOutput::_instance;
+LogOutput* const LogOutput::Stderr = &LogStderrOutput::_instance;
+
+LogOutput::~LogOutput() {
+  os::free(_config_string);
+}
+
+void LogOutput::set_config_string(const char* string) {
+  os::free(_config_string);
+  _config_string = os::strdup_check_oom(string, mtLogging);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logOutput.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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_LOGGING_LOGOUTPUT_HPP
+#define SHARE_VM_LOGGING_LOGOUTPUT_HPP
+
+#include "logging/logDecorators.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogDecorations;
+
+// The base class/interface for log outputs.
+// Keeps track of the latest configuration string,
+// and its selected decorators.
+class LogOutput : public CHeapObj<mtLogging> {
+ protected:
+  LogDecorators _decorators;
+  char* _config_string;
+
+ public:
+  static LogOutput* const Stdout;
+  static LogOutput* const Stderr;
+
+  void set_decorators(const LogDecorators &decorators) {
+    _decorators = decorators;
+  }
+
+  const LogDecorators& decorators() const {
+    return _decorators;
+  }
+
+  const char* config_string() const {
+    return _config_string;
+  }
+
+  LogOutput() : _config_string(NULL) {
+  }
+
+  virtual ~LogOutput();
+  void set_config_string(const char* string);
+
+  virtual const char* name() const = 0;
+  virtual bool initialize(const char* options) = 0;
+  virtual int write(const LogDecorations &decorations, const char* msg) = 0;
+};
+
+#endif // SHARE_VM_LOGGING_LOGOUTPUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logOutputList.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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 "logging/logLevel.hpp"
+#include "logging/logOutputList.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+jint LogOutputList::increase_readers() {
+  jint result = Atomic::add(1, &_active_readers);
+  assert(_active_readers > 0, "Ensure we have consistent state");
+  return result;
+}
+
+jint LogOutputList::decrease_readers() {
+  jint result = Atomic::add(-1, &_active_readers);
+  assert(result >= 0, "Ensure we have consistent state");
+  return result;
+}
+
+void LogOutputList::wait_until_no_readers() const {
+  OrderAccess::storeload();
+  while (_active_readers != 0) {
+    // Busy wait
+  }
+}
+
+void LogOutputList::set_output_level(LogOutput* output, LogLevelType level) {
+  LogOutputNode* node = find(output);
+  if (level == LogLevel::Off && node != NULL) {
+    remove_output(node);
+  } else if (level != LogLevel::Off && node == NULL) {
+    add_output(output, level);
+  } else if (node != NULL) {
+    update_output_level(node, level);
+  }
+}
+
+LogOutputList::LogOutputNode* LogOutputList::find(LogOutput* output) {
+  for (LogOutputNode* node = _level_start[LogLevel::Last]; node != NULL; node = node->_next) {
+    if (output == node->_value) {
+      return node;
+    }
+  }
+  return NULL;
+}
+
+void LogOutputList::remove_output(LogOutputList::LogOutputNode* node) {
+  assert(node != NULL, "Node must be non-null");
+
+  // Remove node from _level_start first
+  bool found = false;
+  for (uint level = LogLevel::First; level < LogLevel::Count; level++) {
+    if (_level_start[level] == node) {
+      found = true;
+      _level_start[level] = node->_next;
+    }
+  }
+
+  // Now remove it from the linked list
+  for (LogOutputNode* cur = _level_start[LogLevel::Last]; cur != NULL; cur = cur->_next) {
+    if (cur->_next == node) {
+      found = true;
+      cur->_next = node->_next;
+      break;
+    }
+  }
+  assert(found, "Node to be removed should always be found");
+
+  wait_until_no_readers();
+  delete node;
+}
+
+void LogOutputList::add_output(LogOutput* output, LogLevelType level) {
+  LogOutputNode* node = new LogOutputNode();
+  node->_value = output;
+  node->_level = level;
+
+  // Set the next pointer to the first node of a lower level
+  for (node->_next = _level_start[level];
+       node->_next != NULL && node->_next->_level == level;
+       node->_next = node->_next->_next) {
+  }
+
+  // Update the _level_start index
+  for (int l = LogLevel::Last; l >= level; l--) {
+    if (_level_start[l] == NULL || _level_start[l]->_level < level) {
+      _level_start[l] = node;
+    }
+  }
+
+  // Add the node the list
+  for (LogOutputNode* cur = _level_start[LogLevel::Last]; cur != NULL; cur = cur->_next) {
+    if (cur != node && cur->_next == node->_next) {
+      cur->_next = node;
+      break;
+    }
+  }
+}
+
+void LogOutputList::update_output_level(LogOutputList::LogOutputNode* node, LogLevelType level) {
+  add_output(node->_value, level);
+  wait_until_no_readers();
+  remove_output(node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logOutputList.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,120 @@
+/*
+ * 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_LOGGING_LOGOUTPUTLIST_HPP
+#define SHARE_VM_LOGGING_LOGOUTPUTLIST_HPP
+
+#include "logging/logLevel.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogOutput;
+
+// Data structure to keep track of log outputs for a given tagset.
+// Essentially a sorted linked list going from error level outputs
+// to outputs of finer levels. Keeps an index from each level to
+// the first node in the list for the corresponding level.
+// This allows a log message on, for example, info level to jump
+// straight into the list where the first info level output can
+// be found. The log message will then be printed on that output,
+// as well as all outputs in nodes that follow in the list (which
+// can be additional info level outputs and/or debug and trace outputs).
+//
+// Each instance keeps track of the number of current readers of the list.
+// To remove a node from the list the node must first be unlinked,
+// and the memory for that node can be freed whenever the removing
+// thread observes an active reader count of 0 (after unlinking it).
+class LogOutputList VALUE_OBJ_CLASS_SPEC {
+ private:
+  struct LogOutputNode : public CHeapObj<mtLogging> {
+    LogOutput*      _value;
+    LogOutputNode*  _next;
+    LogLevelType    _level;
+  };
+
+  LogOutputNode*  _level_start[LogLevel::Count];
+  volatile jint   _active_readers;
+
+  LogOutputNode* find(LogOutput* output);
+  void remove_output(LogOutputNode* node);
+  void add_output(LogOutput* output, LogLevelType level);
+  void update_output_level(LogOutputNode* node, LogLevelType level);
+
+ public:
+  LogOutputList() : _active_readers(0) {
+    for (size_t i = 0; i < LogLevel::Count; i++) {
+      _level_start[i] = NULL;
+    }
+  }
+
+  // Test if the outputlist has an output for the given level.
+  bool is_level(LogLevelType level) {
+    return _level_start[level] != NULL;
+  }
+
+  // Set (add/update/remove) the output to the specified level.
+  void set_output_level(LogOutput* output, LogLevelType level);
+
+  // Bookkeeping functions to keep track of number of active readers/iterators for the list.
+  jint increase_readers();
+  jint decrease_readers();
+  void wait_until_no_readers() const;
+
+  class Iterator VALUE_OBJ_CLASS_SPEC {
+    friend class LogOutputList;
+   private:
+    LogOutputNode*  _current;
+    LogOutputList*  _list;
+    Iterator(LogOutputList* list, LogOutputNode* start) : _current(start), _list(list) {
+    }
+
+   public:
+    ~Iterator() {
+      _list->decrease_readers();
+    }
+
+    LogOutput* operator*() {
+      return _current->_value;
+    }
+
+    void operator++(int) {
+      _current = _current->_next;
+    }
+
+    bool operator!=(const LogOutputNode *ref) const {
+      return _current != ref;
+    }
+  };
+
+  Iterator iterator(LogLevelType level = LogLevel::Last) {
+    increase_readers();
+    return Iterator(this, _level_start[level]);
+  }
+
+  LogOutputNode* end() const {
+    return NULL;
+  }
+};
+
+#endif // SHARE_VM_LOGGING_LOGOUTPUTLIST_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logPrefix.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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_LOGGING_LOGPREFIX_HPP
+#define SHARE_VM_LOGGING_LOGPREFIX_HPP
+
+#include "gc/shared/gcId.hpp"
+#include "logging/logTag.hpp"
+
+// Prefixes prepend each log message for a specified tagset with the given prefix.
+// A prefix consists of a format string and a value or callback. Prefixes are added
+// after the decorations but before the log message.
+//
+// List of prefixes for specific tags and/or tagsets.
+// Syntax: LOG_PREFIX(<printf format>, <value/callback for value>, LOG_TAGS(<chosen log tags>))
+#define LOG_PREFIX_LIST // Currently unused/empty
+
+// The empty prefix, used when there's no prefix defined.
+template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag = LogTag::__NO_TAG>
+struct LogPrefix : public AllStatic {
+  STATIC_ASSERT(GuardTag == LogTag::__NO_TAG);
+  static size_t prefix(char* buf, size_t len) {
+    return 0;
+  }
+};
+
+#define LOG_PREFIX(fmt, fn, ...) \
+template <> struct LogPrefix<__VA_ARGS__> { \
+  static size_t prefix(char* buf, size_t len) { \
+    int ret = jio_snprintf(buf, len, fmt, fn); \
+    assert(ret >= 0, \
+           err_msg("Failed to prefix log message using prefix ('%s', '%s'), log buffer too small?", fmt, #fn)); \
+    return ret; \
+  } \
+};
+LOG_PREFIX_LIST
+#undef LOG_PREFIX
+
+#endif // SHARE_VM_LOGGING_LOGPREFIX_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTag.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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 "logging/logTag.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+const char* LogTag::_name[] = {
+  "", // __NO_TAG
+#define LOG_TAG(name) #name,
+  LOG_TAG_LIST
+#undef LOG_TAG
+};
+
+LogTagType LogTag::from_string(const char* str) {
+  for (uint i = 0; i < LogTag::Count; i++) {
+    if (strcasecmp(str, _name[i]) == 0) {
+      return static_cast<LogTagType>(i);
+    }
+  }
+  return __NO_TAG;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -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.
+ *
+ */
+#ifndef SHARE_VM_LOGGING_LOGTAG_HPP
+#define SHARE_VM_LOGGING_LOGTAG_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// List of available logging tags. New tags should be added here.
+// (The tags 'all', 'disable' and 'help' are special tags that can
+// not be used in log calls, and should not be listed below.)
+#define LOG_TAG_LIST \
+  LOG_TAG(logging)
+
+#define PREFIX_LOG_TAG(T) (LogTag::T)
+
+// Expand a set of log tags to their prefixed names.
+// For error detection purposes, the macro passes one more tag than what is supported.
+// If too many tags are given, a static assert in the log class will fail.
+#define LOG_TAGS_EXPANDED(T0, T1, T2, T3, T4, T5, ...)  PREFIX_LOG_TAG(T0), PREFIX_LOG_TAG(T1), PREFIX_LOG_TAG(T2), \
+                                                        PREFIX_LOG_TAG(T3), PREFIX_LOG_TAG(T4), PREFIX_LOG_TAG(T5)
+// The EXPAND_VARARGS macro is required for MSVC, or it will resolve the LOG_TAGS_EXPANDED macro incorrectly.
+#define EXPAND_VARARGS(x) x
+#define LOG_TAGS(...) EXPAND_VARARGS(LOG_TAGS_EXPANDED(__VA_ARGS__, __NO_TAG, __NO_TAG, __NO_TAG, __NO_TAG, __NO_TAG, __NO_TAG))
+
+// Log tags are used to classify log messages.
+// Each log message can be assigned between 1 to LogTag::MaxTags number of tags.
+// Specifying multiple tags for a log message means that only outputs configured
+// for those exact tags, or a subset of the tags with a wildcard, will see the logging.
+// Multiple tags should be comma separated, e.g. log_error(tag1, tag2)("msg").
+class LogTag : public AllStatic {
+ public:
+  // The maximum number of tags that a single log message can have.
+  // E.g. there might be hundreds of different tags available,
+  // but a specific log message can only be tagged with up to MaxTags of those.
+  static const size_t MaxTags = 5;
+
+  enum type {
+    __NO_TAG,
+#define LOG_TAG(name) name,
+    LOG_TAG_LIST
+#undef LOG_TAG
+    Count
+  };
+
+  static const char* name(LogTag::type tag) {
+    return _name[tag];
+  }
+
+  static LogTag::type from_string(const char *str);
+
+ private:
+  static const char* _name[];
+};
+
+typedef LogTag::type LogTagType;
+
+#endif // SHARE_VM_LOGGING_LOGTAG_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,160 @@
+/*
+ * 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 "logging/logTagLevelExpression.hpp"
+#include "logging/logTagSet.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/os.inline.hpp"
+
+const char* LogTagLevelExpression::DefaultExpressionString = "all";
+
+LogTagLevelExpression::~LogTagLevelExpression() {
+  os::free(_string);
+}
+
+void LogTagLevelExpression::clear() {
+  _ntags = 0;
+  _ncombinations = 0;
+  for (size_t combination = 0; combination < MaxCombinations; combination++) {
+    _level[combination] = LogLevel::Invalid;
+    _allow_other_tags[combination] = false;
+    for (size_t tag = 0; tag < LogTag::MaxTags; tag++) {
+      _tags[combination][tag] = LogTag::__NO_TAG;
+    }
+  }
+  os::free(_string);
+  _string = NULL;
+}
+
+bool LogTagLevelExpression::parse(const char* str, outputStream* errstream) {
+  bool success = true;
+  clear();
+  if (str == NULL || strcmp(str, "") == 0) {
+    str = DefaultExpressionString;
+  }
+  char* copy = os::strdup_check_oom(str, mtLogging);
+  // Split string on commas
+  for (char *comma_pos = copy, *cur = copy; success && comma_pos != NULL; cur = comma_pos + 1) {
+    if (_ncombinations == MaxCombinations) {
+      if (errstream != NULL) {
+        errstream->print_cr("Can not have more than " SIZE_FORMAT " tag combinations in a what-expression.",
+                            MaxCombinations);
+      }
+      success = false;
+      break;
+    }
+
+    comma_pos = strchr(cur, ',');
+    if (comma_pos != NULL) {
+      *comma_pos = '\0';
+    }
+
+    // Parse the level, if specified
+    LogLevelType level = LogLevel::Unspecified;
+    char* equals = strchr(cur, '=');
+    if (equals != NULL) {
+      level = LogLevel::from_string(equals + 1);
+      if (level == LogLevel::Invalid) {
+        if (errstream != NULL) {
+          errstream->print_cr("Invalid level '%s' in what-expression.", equals + 1);
+        }
+        success = false;
+        break;
+      }
+      *equals = '\0'; // now ignore "=level" part of substr
+    }
+    set_level(level);
+
+    // Parse special tags such as 'all'
+    if (strcmp(cur, "all") == 0) {
+      set_allow_other_tags();
+      new_combination();
+      continue;
+    }
+
+    // Check for '*' suffix
+    char* asterisk_pos = strchr(cur, '*');
+    if (asterisk_pos != NULL && asterisk_pos[1] == '\0') {
+      set_allow_other_tags();
+      *asterisk_pos = '\0';
+    }
+
+    // Parse the tag expression (t1+t2+...+tn)
+    char* plus_pos;
+    char* cur_tag = cur;
+    do {
+      plus_pos = strchr(cur_tag, '+');
+      if (plus_pos != NULL) {
+        *plus_pos = '\0';
+      }
+      LogTagType tag = LogTag::from_string(cur_tag);
+      if (tag == LogTag::__NO_TAG) {
+        if (errstream != NULL) {
+          errstream->print_cr("Invalid tag '%s' in what-expression.", cur_tag);
+        }
+        success = false;
+        break;
+      }
+      if (_ntags == LogTag::MaxTags) {
+        if (errstream != NULL) {
+          errstream->print_cr("Tag combination exceeds the maximum of " SIZE_FORMAT " tags.",
+                              LogTag::MaxTags);
+        }
+        success = false;
+        break;
+      }
+      add_tag(tag);
+      cur_tag = plus_pos + 1;
+    } while (plus_pos != NULL);
+
+    new_combination();
+  }
+
+  // Save the (unmodified) string for printing purposes.
+  _string = copy;
+  strcpy(_string, str);
+
+  return success;
+}
+
+LogLevelType LogTagLevelExpression::level_for(const LogTagSet& ts) const {
+  LogLevelType level = LogLevel::Off;
+  for (size_t combination = 0; combination < _ncombinations; combination++) {
+    bool contains_all = true;
+    size_t tag_idx;
+    for (tag_idx = 0; tag_idx < LogTag::MaxTags && _tags[combination][tag_idx] != LogTag::__NO_TAG; tag_idx++) {
+      if (!ts.contains(_tags[combination][tag_idx])) {
+        contains_all = false;
+        break;
+      }
+    }
+    // All tags in the expression must be part of the tagset,
+    // and either the expression allows other tags (has a wildcard),
+    // or the number of tags in the expression and tagset must match.
+    if (contains_all && (_allow_other_tags[combination] || tag_idx == ts.ntags())) {
+      level = _level[combination];
+    }
+  }
+  return level;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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_LOGGING_LOGTAGLEVELEXPRESSION_HPP
+#define SHARE_VM_LOGGING_LOGTAGLEVELEXPRESSION_HPP
+
+#include "logging/logLevel.hpp"
+#include "logging/logTag.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LogTagSet;
+
+// Class used to temporary encode a 'what'-expression during log configuration.
+// Consists of a combination of tags and levels, e.g. "tag1+tag2=level1,tag3*=level2".
+class LogTagLevelExpression : public StackObj {
+ private:
+  static const size_t MaxCombinations = 32;
+  static const char* DefaultExpressionString;
+
+  size_t        _ntags, _ncombinations;
+  LogTagType    _tags[MaxCombinations][LogTag::MaxTags];
+  LogLevelType  _level[MaxCombinations];
+  bool          _allow_other_tags[MaxCombinations];
+  char*         _string;
+
+  void new_combination() {
+    _ncombinations++;
+    _ntags = 0;
+  }
+
+  void add_tag(LogTagType tag) {
+    assert(_ntags < LogTag::MaxTags, "Can't have more tags than MaxTags!");
+    _tags[_ncombinations][_ntags++] = tag;
+  }
+
+  void set_level(LogLevelType level) {
+    _level[_ncombinations] = level;
+  }
+
+  void set_allow_other_tags() {
+    _allow_other_tags[_ncombinations] = true;
+  }
+
+  void clear();
+
+ public:
+  LogTagLevelExpression() : _ntags(0), _ncombinations(0), _string(NULL) {
+  }
+
+  const char* to_string() const {
+    return _string;
+  }
+
+  ~LogTagLevelExpression();
+  bool parse(const char* str, outputStream* errstream = NULL);
+  LogLevelType level_for(const LogTagSet& ts) const;
+};
+
+#endif // SHARE_VM_LOGGING_LOGTAGLEVELEXPRESSION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTagSet.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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 "logging/logDecorations.hpp"
+#include "logging/logLevel.hpp"
+#include "logging/logOutput.hpp"
+#include "logging/logTag.hpp"
+#include "logging/logTagSet.hpp"
+
+LogTagSet*  LogTagSet::_list      = NULL;
+size_t      LogTagSet::_ntagsets  = 0;
+
+// This constructor is called only during static initialization.
+// See the declaration in logTagSet.hpp for more information.
+LogTagSet::LogTagSet(LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4)
+    : _next(_list) {
+  _tag[0] = t0;
+  _tag[1] = t1;
+  _tag[2] = t2;
+  _tag[3] = t3;
+  _tag[4] = t4;
+  for (_ntags = 0; _ntags < LogTag::MaxTags && _tag[_ntags] != LogTag::__NO_TAG; _ntags++) {
+  }
+  _list = this;
+  _ntagsets++;
+
+  // Set the default output to warning and error level for all new tagsets.
+  _output_list.set_output_level(LogOutput::Stderr, LogLevel::Default);
+}
+
+bool LogTagSet::is_level(LogLevelType level) {
+  return _output_list.is_level(level);
+}
+
+void LogTagSet::update_decorators(const LogDecorators& decorator) {
+  LogDecorators new_decorators = decorator;
+  for (LogOutputList::Iterator it = _output_list.iterator(); it != _output_list.end(); it++) {
+    new_decorators.combine_with((*it)->decorators());
+  }
+  _decorators = new_decorators;
+}
+
+bool LogTagSet::has_output(const LogOutput* output) {
+  for (LogOutputList::Iterator it = _output_list.iterator(); it != _output_list.end(); it++) {
+    if (*it == output) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void LogTagSet::log(LogLevelType level, const char* msg) {
+  LogDecorations decorations(level, *this, _decorators);
+  for (LogOutputList::Iterator it = _output_list.iterator(level); it != _output_list.end(); it++) {
+    (*it)->write(decorations, msg);
+  }
+}
+
+int LogTagSet::label(char* buf, size_t len)  {
+  int tot_written = 0;
+  for (size_t i = 0; i < _ntags; i++) {
+    int written = jio_snprintf(buf + tot_written, len - tot_written, "%s%s",
+                               (i == 0 ? "" : ","),
+                               LogTag::name(_tag[i]));
+    if (written < 0) {
+      return -1;
+    }
+    tot_written += written;
+  }
+  return tot_written;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTagSet.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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_LOGGING_LOGTAGSET_HPP
+#define SHARE_VM_LOGGING_LOGTAGSET_HPP
+
+#include "logging/logDecorators.hpp"
+#include "logging/logLevel.hpp"
+#include "logging/logOutputList.hpp"
+#include "logging/logTag.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// The tagset represents a combination of tags that occur in a log call somewhere.
+// Tagsets are created automatically by the LogTagSetMappings and should never be
+// instantiated directly somewhere else.
+class LogTagSet VALUE_OBJ_CLASS_SPEC {
+ private:
+  static LogTagSet* _list;
+  static size_t     _ntagsets;
+
+  LogTagSet* const  _next;
+  size_t            _ntags;
+  LogTagType        _tag[LogTag::MaxTags];
+
+  LogOutputList     _output_list;
+  LogDecorators     _decorators;
+
+  // Keep constructor private to prevent incorrect instantiations of this class.
+  // Only LogTagSetMappings can create/contain instances of this class.
+  // The constructor links all tagsets together in a global list of tagsets.
+  // This list is used during configuration to be able to update all tagsets
+  // and their configurations to reflect the new global log configuration.
+  LogTagSet(LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4);
+
+  template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4>
+  friend class LogTagSetMapping;
+
+ public:
+  static LogTagSet* first() {
+    return _list;
+  }
+
+  LogTagSet* next() {
+    return _next;
+  }
+
+  size_t ntags() const {
+    return _ntags;
+  }
+
+  bool contains(LogTagType tag) const {
+    for (size_t i = 0; _tag[i] != LogTag::__NO_TAG; i++) {
+      if (tag == _tag[i]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void set_output_level(LogOutput* output, LogLevelType level) {
+    _output_list.set_output_level(output, level);
+  }
+
+  // Refresh the decorators for this tagset to contain the decorators for all
+  // of its current outputs combined with the given decorators.
+  void update_decorators(const LogDecorators& decorator);
+
+  int label(char *buf, size_t len);
+  bool has_output(const LogOutput* output);
+  bool is_level(LogLevelType level);
+  void log(LogLevelType level, const char* msg);
+};
+
+template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG,
+          LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG>
+class LogTagSetMapping : public AllStatic {
+private:
+  static LogTagSet _tagset;
+
+public:
+  static LogTagSet& tagset() {
+    return _tagset;
+  }
+};
+
+// Instantiate the static field _tagset for all tagsets that are used for logging somewhere.
+// (This must be done here rather than the .cpp file because it's a template.)
+// Each combination of tags used as template arguments to the Log class somewhere (via macro or not)
+// will instantiate the LogTagSetMapping template, which in turn creates the static field for that
+// tagset. This _tagset contains the configuration for those tags.
+template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4>
+LogTagSet LogTagSetMapping<T0, T1, T2, T3, T4>::_tagset(T0, T1, T2, T3, T4);
+
+#endif // SHARE_VM_LOGGING_LOGTAGSET_HPP
--- a/hotspot/src/share/vm/memory/allocation.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -154,8 +154,9 @@
   mtChunk             = 0x0C,  // chunk that holds content of arenas
   mtTest              = 0x0D,  // Test type for verifying NMT
   mtTracing           = 0x0E,  // memory used for Tracing
-  mtNone              = 0x0F,  // undefined
-  mt_number_of_types  = 0x10   // number of memory types (mtDontTrack
+  mtLogging           = 0x0F,  // memory for logging
+  mtNone              = 0x10,  // undefined
+  mt_number_of_types  = 0x11   // number of memory types (mtDontTrack
                                  // is not included as validate type)
 };
 
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -128,6 +128,7 @@
 # include "interpreter/templateInterpreter.hpp"
 # include "interpreter/templateTable.hpp"
 # include "jvmtifiles/jvmti.h"
+# include "logging/log.hpp"
 # include "memory/allocation.hpp"
 # include "memory/allocation.inline.hpp"
 # include "memory/heap.hpp"
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -32,6 +32,7 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/referenceProcessor.hpp"
 #include "gc/shared/taskqueue.hpp"
+#include "logging/logConfiguration.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
@@ -3190,6 +3191,26 @@
       if (FLAG_SET_CMDLINE(bool, PrintGCTimeStamps, true) != Flag::SUCCESS) {
         return JNI_EINVAL;
       }
+    } else if (match_option(option, "-Xlog", &tail)) {
+      bool ret = false;
+      if (strcmp(tail, ":help") == 0) {
+        LogConfiguration::print_command_line_help(defaultStream::output_stream());
+        vm_exit(0);
+      } else if (strcmp(tail, ":disable") == 0) {
+        LogConfiguration::disable_logging();
+        ret = true;
+      } else if (*tail == '\0') {
+        ret = LogConfiguration::parse_command_line_arguments();
+        assert(ret, "-Xlog without arguments should never fail to parse");
+      } else if (*tail == ':') {
+        ret = LogConfiguration::parse_command_line_arguments(tail + 1);
+      }
+      if (ret == false) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "Invalid -Xlog option '-Xlog%s'\n",
+                    tail);
+        return JNI_EINVAL;
+      }
     // JNI hooks
     } else if (match_option(option, "-Xcheck", &tail)) {
       if (!strcmp(tail, ":jni")) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -127,6 +127,7 @@
 Mutex*   Management_lock              = NULL;
 Monitor* Service_lock                 = NULL;
 Monitor* PeriodicTask_lock            = NULL;
+Mutex*   LogConfiguration_lock        = NULL;
 
 #ifdef INCLUDE_TRACE
 Mutex*   JfrStacktrace_lock           = NULL;
@@ -282,6 +283,7 @@
   if (WhiteBoxAPI) {
     def(Compilation_lock           , Monitor, leaf,        false, Monitor::_safepoint_check_never);
   }
+  def(LogConfiguration_lock        , Mutex,   nonleaf,     false, Monitor::_safepoint_check_always);
 
 #ifdef INCLUDE_TRACE
   def(JfrMsg_lock                  , Monitor, leaf,        true,  Monitor::_safepoint_check_always);
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -126,6 +126,7 @@
 extern Mutex*   Management_lock;                 // a lock used to serialize JVM management
 extern Monitor* Service_lock;                    // a lock used for service thread operation
 extern Monitor* PeriodicTask_lock;               // protects the periodic task structure
+extern Mutex*   LogConfiguration_lock;           // protects configuration of logging
 
 #ifdef INCLUDE_TRACE
 extern Mutex*   JfrStacktrace_lock;              // used to guard access to the JFR stacktrace table
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -37,6 +37,7 @@
 #include "interpreter/linkResolver.hpp"
 #include "interpreter/oopMapCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
+#include "logging/logConfiguration.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.inline.hpp"
@@ -3306,6 +3307,10 @@
   // Initialize the os module before using TLS
   os::init();
 
+  // Record VM creation timing statistics
+  TraceVmCreationTime create_vm_timer;
+  create_vm_timer.start();
+
   // Initialize system properties.
   Arguments::init_system_properties();
 
@@ -3315,6 +3320,9 @@
   // Update/Initialize System properties after JDK version number is known
   Arguments::init_version_specific_system_properties();
 
+  // Make sure to initialize log configuration *before* parsing arguments
+  LogConfiguration::initialize(create_vm_timer.begin_time());
+
   // Parse arguments
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
@@ -3341,10 +3349,6 @@
 
   HOTSPOT_VM_INIT_BEGIN();
 
-  // Record VM creation timing statistics
-  TraceVmCreationTime create_vm_timer;
-  create_vm_timer.start();
-
   // Timing (must come after argument parsing)
   TraceTime timer("Create VM", TraceStartupTime);
 
@@ -3492,6 +3496,7 @@
   // debug stuff, that does not work until all basic classes have been initialized.
   set_init_completed();
 
+  LogConfiguration::post_initialize();
   Metaspace::post_initialize();
 
   HOTSPOT_VM_INIT_END();
@@ -3966,6 +3971,8 @@
   // exit_globals() will delete tty
   exit_globals();
 
+  LogConfiguration::finalize();
+
   return true;
 }
 
--- a/hotspot/src/share/vm/services/management.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/services/management.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -118,6 +118,10 @@
   void start()
   { _timer.update_to(0); _begin_time = os::javaTimeMillis(); }
 
+  jlong begin_time() const {
+    return _begin_time;
+  }
+
   /**
    * Only call this if initialization completes successfully; it will
    * crash if PerfMemory_exit() has already been called (usually by
--- a/hotspot/src/share/vm/services/nmtCommon.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/services/nmtCommon.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -40,6 +40,7 @@
   "Arena Chunk",
   "Test",
   "Tracing",
+  "Logging",
   "Unknown"
 };
 
--- a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -84,7 +84,10 @@
         return _committed_regions.insert_after(committed_rgn, node) != NULL;
       }
     }
-    assert(rgn->contain_region(addr, size), "Must cover this region");
+    // If we have reached this point, then we are trying to commit a region that overlaps with some existing committed regions.
+    remove_uncommitted_region(addr, size);
+    add_committed_region(committed_rgn);
+
     return true;
   } else {
     // New committed region
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Mon Sep 28 15:05:02 2015 +0200
@@ -1440,3 +1440,14 @@
 }
 
 #endif
+
+void logStream::write(const char* s, size_t len) {
+  if (len > 0 && s[len - 1] == '\n') {
+    _current_line.write(s, len - 1);
+    _log_func(_current_line.as_string());
+    _current_line.reset();
+  } else {
+    _current_line.write(s, len);
+    update_position(s, len);
+  }
+}
--- a/hotspot/src/share/vm/utilities/ostream.hpp	Thu Sep 24 11:38:26 2015 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.hpp	Mon Sep 28 15:05:02 2015 +0200
@@ -235,6 +235,18 @@
   void flush() {};
 };
 
+class logStream : public outputStream {
+private:
+  stringStream _current_line;
+  void (*_log_func)(const char* fmt, ...);
+public:
+  void write(const char* s, size_t len);
+  logStream(void (*log_func)(const char* fmt, ...)) : _log_func(log_func) {}
+  ~logStream() {
+    guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?");
+  }
+};
+
 class gcLogFileStream : public fileStream {
  protected:
   const char*  _file_name;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/mixedgc/TestLogging.java	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,173 @@
+/*
+ * 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 TestLogging
+ * @summary Check that a mixed GC is reflected in the gc logs
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @library /testlibrary /../../test/lib
+ * @modules java.management
+ * @build sun.hotspot.WhiteBox gc.g1.mixedgc.TestLogging
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver gc.g1.mixedgc.TestLogging
+ */
+
+package gc.g1.mixedgc;
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * Test spawns MixedGCProvoker in a separate VM and expects to find a message
+ * telling that a mixed gc has happened
+ */
+public class TestLogging {
+    private static final String[] COMMON_OPTIONS = new String[]{
+            "-Xbootclasspath/a:.", "-XX:+UseG1GC",
+            "-XX:+UnlockExperimentalVMOptions",
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:+WhiteBoxAPI",
+            "-XX:SurvivorRatio=1", // Survivor-to-eden ratio is 1:1
+            "-Xms10M", "-Xmx10M",
+            "-XX:MaxTenuringThreshold=1", // promote objects after first gc
+            "-XX:InitiatingHeapOccupancyPercent=0", // marking cycle happens
+            // each time
+            "-XX:G1MixedGCCountTarget=4",
+            "-XX:MaxGCPauseMillis=30000", // to have enough time
+            "-XX:G1HeapRegionSize=1m", "-XX:G1HeapWastePercent=0",
+            "-XX:G1MixedGCLiveThresholdPercent=100"};
+
+    public static final int ALLOCATION_SIZE = 20000;
+    public static final int ALLOCATION_COUNT = 15;
+
+    public static void main(String args[]) throws Exception {
+        // Test turns logging on by giving -XX:+PrintGC flag
+        test("-XX:+PrintGC");
+        // Test turns logging on by giving -XX:+PrintGCDetails
+        test("-XX:+PrintGCDetails");
+    }
+
+    private static void test(String vmFlag) throws Exception {
+        System.out.println(String.format("%s: running with %s flag", TestLogging.class.getSimpleName(), vmFlag));
+        OutputAnalyzer output = spawnMixedGCProvoker(vmFlag);
+        System.out.println(output.getStdout());
+        output.shouldHaveExitValue(0);
+        output.shouldContain("GC pause (G1 Evacuation Pause) (mixed)");
+    }
+
+    /**
+     * Method spawns MixedGCProvoker with addition flags set
+     *
+     * @parameter extraFlags -flags to be added to the common options set
+     */
+    private static OutputAnalyzer spawnMixedGCProvoker(String... extraFlags)
+            throws Exception {
+        List<String> testOpts = new ArrayList<>();
+        Collections.addAll(testOpts, COMMON_OPTIONS);
+        Collections.addAll(testOpts, extraFlags);
+        testOpts.add(MixedGCProvoker.class.getName());
+        System.out.println(testOpts);
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false,
+                testOpts.toArray(new String[testOpts.size()]));
+        return new OutputAnalyzer(pb.start());
+    }
+}
+
+/**
+ * Utility class to guarantee a mixed GC. The class allocates several arrays and
+ * promotes them to the oldgen. After that it tries to provoke mixed GC by
+ * allocating new objects.
+ *
+ * The necessary condition for guaranteed mixed GC is running MixedGCProvoker is
+ * running in VM with the following flags: -XX:MaxTenuringThreshold=1, -Xms10M,
+ * -Xmx10M, -XX:G1MixedGCLiveThresholdPercent=100, -XX:G1HeapWastePercent=0,
+ * -XX:G1HeapRegionSize=1m
+ */
+class MixedGCProvoker {
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
+    private static final List<byte[]> liveOldObjects = new ArrayList<>();
+    private static final List<byte[]> newObjects = new ArrayList<>();
+
+    private static void allocateOldObjects() throws Exception {
+        List<byte[]> deadOldObjects = new ArrayList<>();
+        // Allocates buffer and promotes it to the old gen. Mix live and dead old
+        // objects
+        for (int i = 0; i < TestLogging.ALLOCATION_COUNT; ++i) {
+            liveOldObjects.add(new byte[TestLogging.ALLOCATION_SIZE * 10]);
+            deadOldObjects.add(new byte[TestLogging.ALLOCATION_SIZE * 10]);
+        }
+
+        // need only 2 promotions to promote objects to the old gen
+        WB.youngGC();
+        WB.youngGC();
+        // check it is promoted & keep alive
+        Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
+                "List of the objects is suppose to be in OldGen");
+        Asserts.assertTrue(WB.isObjectInOldGen(deadOldObjects),
+                "List of the objects is suppose to be in OldGen");
+    }
+
+
+    /**
+     * Waits until Concurent Mark Cycle finishes
+     * @param wb  Whitebox instance
+     * @param sleepTime sleep time
+     */
+    public static void waitTillCMCFinished(WhiteBox wb, int sleepTime) {
+        while (wb.g1InConcurrentMark()) {
+            if (sleepTime > -1) {
+                try {
+                    Thread.sleep(sleepTime);
+                } catch (InterruptedException e) {
+                    System.out.println("Got InterruptedException while waiting for ConcMarkCycle to finish");
+                }
+            }
+        }
+    }
+
+
+
+    public static void main(String args[]) throws Exception {
+        // allocate old objects
+        allocateOldObjects();
+        waitTillCMCFinished(WB, 0);
+        WB.g1StartConcMarkCycle();
+        waitTillCMCFinished(WB, 0);
+
+        WB.youngGC();
+        System.out.println("Allocating new objects to provoke mixed GC");
+        // allocate more objects to provoke GC
+        for (int i = 0; i < (TestLogging.ALLOCATION_COUNT * 20); i++) {
+            newObjects.add(new byte[TestLogging.ALLOCATION_SIZE]);
+        }
+        // check that liveOldObjects still alive
+        Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
+                "List of the objects is suppose to be in OldGen");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/logging/TestPrintReferences.java	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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 TestPrintReferences
+ * @bug 8136991
+ * @summary Validate the reference processing logging
+ * @key gc
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestPrintReferences {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb_enabled =
+      ProcessTools.createJavaProcessBuilder("-XX:+PrintGCDetails", "-XX:+PrintReferenceGC", "-Xmx10M", GCTest.class.getName());
+    OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
+
+    String countRegex = "[0-9]+ refs";
+    String timeRegex = "[0-9]+[.,][0-9]+ secs";
+
+    output.shouldMatch(
+      "#[0-9]+: \\[SoftReference, " + countRegex + ", " + timeRegex + "\\]" +
+      "#[0-9]+: \\[WeakReference, " + countRegex + ", " + timeRegex + "\\]" +
+      "#[0-9]+: \\[FinalReference, " + countRegex + ", " + timeRegex + "\\]" +
+      "#[0-9]+: \\[PhantomReference, " + countRegex + ", " + timeRegex + "\\]" +
+      "#[0-9]+: \\[JNI Weak Reference, (" + countRegex + ", )?" + timeRegex + "\\]");
+
+    output.shouldHaveExitValue(0);
+  }
+
+  static class GCTest {
+    public static void main(String [] args) {
+      System.gc();
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/TestVMOptionsFile.java	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,620 @@
+/*
+ * 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 8061999
+ * @summary Test "-XX:VMOptionsFile" VM option
+ * @library /testlibrary
+ * @modules jdk.management
+ * @run main TestVMOptionsFile
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.DynamicVMOption;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclEntryPermission;
+import java.nio.file.attribute.AclEntryType;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.nio.file.attribute.UserPrincipal;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.LinkedHashSet;
+
+public class TestVMOptionsFile {
+
+    /* Empty VM Option file */
+    private static final String VM_OPTION_FILE_EMPTY = "optionfile_empty";
+    /* VM Option file with tabs and spaces */
+    private static final String VM_OPTION_FILE_TABS_AND_SPACES = "optionfile_only_tabsandspaces";
+    /* Various valid VM Option files */
+    private static final String VM_OPTION_FILE_1 = "optionfile_1";
+    private static final String VM_OPTION_FILE_2 = "optionFILE_2";
+    private static final String VM_OPTION_FILE_3 = "optionfile_3";
+    private static final String VM_OPTION_FILE_QUOTE = "optionfile_quote";
+    private static final String VM_OPTION_FILE_QUOTE_MAX_SIZE = "optionfile_quote_max_size";
+    /* 2 VM Option files with unmatched quotes */
+    private static final String VM_OPTION_FILE_UNMATCHED_QUOTE_1 = "optionfile_unmatched_quote_1";
+    private static final String VM_OPTION_FILE_UNMATCHED_QUOTE_2 = "optionfile_unmatched_quote_2";
+    /* Name of the file with flags for VM_OPTION_FILE_2 Option file */
+    private static final String FLAGS_FILE = "flags_file";
+    /* VM Option file with a lot of options with quote on separate lines */
+    private static final String VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE = "optionfile_lot_of_options_quote";
+    /* Number of properties defined in VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE */
+    private static final int NUM_OF_PROP_IN_FILE_LOT_OF_OPTIONS_QUOTE = 65;
+    /* VM Option file with bad option in it */
+    private static final String VM_OPTION_FILE_WITH_BAD_OPTION = "optionfile_bad_option";
+    /* VM Option file with "-XX:VMOptionsFile=" option in it */
+    private static final String VM_OPTION_FILE_WITH_VM_OPTION_FILE = "optionfile_with_optionfile";
+    /* VM Option file with "-XX:VMOptionsFile=" option in it, where file is the same option file */
+    private static final String VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE = "optionfile_with_same_optionfile";
+    /* VM Option file without read permissions(not accessible) */
+    private static final String VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS = "optionfile_wo_read_perm";
+    /* VM Option file with long property(file size is 1024 bytes) */
+    private static final String VM_OPTION_FILE_WITH_LONG_PROPERTY = "optionfile_long_property";
+    /* VM Option file with very long property(file size is more than 1024 bytes) */
+    private static final String VM_OPTION_FILE_WITH_VERY_LONG_PROPERTY = "optionfile_very_long_property";
+    /* VM Option file which does not exist */
+    private static final String NOT_EXISTING_FILE = "not_exist_junk2123";
+
+    /* JAVA_TOOL_OPTIONS environment variable */
+    private static final String JAVA_TOOL_OPTIONS = "JAVA_TOOL_OPTIONS";
+    /* _JAVA_OPTIONS environment variable */
+    private static final String JAVA_OPTIONS = "_JAVA_OPTIONS";
+
+    /* Exit code for JVM, zero - for success, non-zero for failure */
+    private static final int JVM_SUCCESS = 0;
+    private static final int JVM_FAIL_WITH_EXIT_CODE_1 = 1;
+
+    /* Current working directory */
+    private static final String CURRENT_DIR = System.getProperty("user.dir");
+
+    /* Source directory */
+    private static final String SOURCE_DIR = System.getProperty("test.src", ".");
+
+    /* VM Options which are passed to the JVM */
+    private static final List<String> VMParams = new ArrayList<>();
+    /* Argument passed to the PrintPropertyAndOptions.main */
+    private static final Set<String> appParams = new LinkedHashSet<>();
+
+    private static OutputAnalyzer output;
+
+    /*
+     * Get absoulte path to file from folder with sources
+     */
+    private static String getAbsolutePathFromSource(String fileName) {
+        return SOURCE_DIR + File.separator + fileName;
+    }
+
+    /*
+     * Make file non-readable by modifying its permissions.
+     * If file supports "posix" attributes, then modify it.
+     * Otherwise check for "acl" attributes.
+     */
+    private static void makeFileNonReadable(String file) throws IOException {
+        Path filePath = Paths.get(file);
+        Set<String> supportedAttr = filePath.getFileSystem().supportedFileAttributeViews();
+
+        if (supportedAttr.contains("posix")) {
+            Files.setPosixFilePermissions(filePath, PosixFilePermissions.fromString("-w--w----"));
+        } else if (supportedAttr.contains("acl")) {
+            UserPrincipal fileOwner = Files.getOwner(filePath);
+
+            AclFileAttributeView view = Files.getFileAttributeView(filePath, AclFileAttributeView.class);
+
+            AclEntry entry = AclEntry.newBuilder()
+                    .setType(AclEntryType.DENY)
+                    .setPrincipal(fileOwner)
+                    .setPermissions(AclEntryPermission.READ_DATA)
+                    .build();
+
+            List<AclEntry> acl = view.getAcl();
+            acl.add(0, entry);
+            view.setAcl(acl);
+        }
+    }
+
+    private static void copyFromSource(String fileName) throws IOException {
+        Files.copy(Paths.get(getAbsolutePathFromSource(fileName)),
+                Paths.get(fileName), StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    private static void createOptionFiles() throws IOException {
+        FileWriter fw = new FileWriter(VM_OPTION_FILE_WITH_VM_OPTION_FILE);
+
+        /* Create VM option file with following parameters "-XX:VMOptionFile=<absolute_path_to_the_VM_option_file> */
+        fw.write("-XX:VMOptionsFile=" + getAbsolutePathFromSource(VM_OPTION_FILE_1));
+        fw.close();
+
+        /* Create VM option file with following parameters "-XX:MinHeapFreeRatio=12 -XX:VMOptionFile=<absolute_path_to_the_same_VM_option_file> */
+        fw = new FileWriter(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE);
+        fw.write("-XX:MinHeapFreeRatio=12 -XX:VMOptionsFile=" + (new File(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE)).getCanonicalPath());
+        fw.close();
+
+        /* Copy valid VM option file and change its permission to make it not accessible */
+        Files.copy(Paths.get(getAbsolutePathFromSource(VM_OPTION_FILE_1)),
+                Paths.get(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS),
+                StandardCopyOption.REPLACE_EXISTING);
+
+        makeFileNonReadable(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS);
+
+        /* Copy valid VM option file to perform test with relative path */
+        copyFromSource(VM_OPTION_FILE_2);
+
+        /* Copy flags file to the current working folder */
+        copyFromSource(FLAGS_FILE);
+
+        /* Create a new empty file */
+        new File(VM_OPTION_FILE_EMPTY).createNewFile();
+    }
+
+    /*
+     * Add parameters to the VM Parameters list
+     */
+    private static void addVMParam(String... params) {
+        VMParams.addAll(Arrays.asList(params));
+    }
+
+    /*
+     * Add property name to the application arguments list
+     */
+    private static void addPropertiesToCheck(String... params) {
+        for (String param : params) {
+            appParams.add("property=" + param);
+        }
+    }
+
+    /*
+     * Add VM option name to the application arguments list
+     */
+    private static void addVMOptionsToCheck(String... params) {
+        for (String param : params) {
+            appParams.add("vmoption=" + param);
+        }
+    }
+
+    /*
+     * Add property to the VM Params list and to the application arguments list
+     */
+    private static void addProperty(String propertyName, String propertyValue) {
+        addVMParam("-D" + propertyName + "=" + propertyValue);
+        addPropertiesToCheck(propertyName);
+    }
+
+    /*
+     * Add "-XX:VMOptionsfile" parameter to the VM Params list
+     */
+    private static void addVMOptionsFile(String fileName) {
+        addVMParam("-XX:VMOptionsFile=" + fileName);
+    }
+
+    private static void outputShouldContain(String expectedString) {
+        output.shouldContain(expectedString);
+    }
+
+    private static void outputShouldNotContain(String expectedString) {
+        output.shouldNotContain(expectedString);
+    }
+
+    private static ProcessBuilder createProcessBuilder() throws Exception {
+        ProcessBuilder pb;
+        List<String> runJava = new ArrayList<>();
+
+        runJava.addAll(VMParams);
+        runJava.add(PrintPropertyAndOptions.class.getName());
+        runJava.addAll(appParams);
+
+        pb = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0]));
+
+        VMParams.clear();
+        appParams.clear();
+
+        return pb;
+    }
+
+    private static void runJavaCheckExitValue(ProcessBuilder pb, int expectedExitValue) throws Exception {
+        output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(expectedExitValue);
+    }
+
+    private static void runJavaCheckExitValue(int expectedExitValue) throws Exception {
+        runJavaCheckExitValue(createProcessBuilder(), expectedExitValue);
+    }
+
+    /*
+     * Update environment variable in passed ProcessBuilder object to the passed value
+     */
+    private static void updateEnvironment(ProcessBuilder pb, String name, String value) {
+        pb.environment().put(name, value);
+    }
+
+    /*
+     * Check property value by examining output
+     */
+    private static void checkProperty(String property, String value) {
+        outputShouldContain("Property " + property + "=" + value);
+    }
+
+    /*
+     * Check VM Option value by examining output
+     */
+    private static void checkVMOption(String vmOption, String value) {
+        outputShouldContain("VM Option " + vmOption + "=" + value);
+    }
+
+    private static void testVMOptions() throws Exception {
+        StringBuilder longProperty = new StringBuilder();
+
+        /* Check that empty VM Option file is accepted without errors */
+        addVMOptionsFile(VM_OPTION_FILE_EMPTY);
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+
+        /* Check that VM Option file with tabs and spaces is accepted without errors */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_TABS_AND_SPACES));
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+
+        /* Check that parameters are gotten from first VM Option file. Pass absolute path to the VM Option file */
+        addVMParam("-showversion");
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1));
+        addPropertiesToCheck("optfile_1");
+        addVMOptionsToCheck("SurvivorRatio", "MinHeapFreeRatio");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+        outputShouldContain("interpreted mode");
+        checkProperty("optfile_1", "option_file_1");
+        checkVMOption("SurvivorRatio", "16");
+        checkVMOption("MinHeapFreeRatio", "22");
+
+        /*
+         * Check that parameters are gotten from second VM Option file which also contains flags file.
+         * Flags file and option file contains NewRatio, but since options from VM Option file
+         * are processed later NewRatio should be set to value from VM Option file
+         * Pass relative path to the VM Option file in form "vmoptionfile"
+         */
+        addVMOptionsFile(VM_OPTION_FILE_2);
+        addPropertiesToCheck("javax.net.ssl.keyStorePassword");
+        addVMOptionsToCheck("UseGCOverheadLimit", "NewRatio", "MinHeapFreeRatio", "MaxFDLimit", "AlwaysPreTouch");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+        checkProperty("javax.net.ssl.keyStorePassword", "someVALUE123+");
+        checkVMOption("UseGCOverheadLimit", "true");
+        checkVMOption("NewRatio", "4");
+        checkVMOption("MinHeapFreeRatio", "3");
+        checkVMOption("MaxFDLimit", "true");
+        checkVMOption("AlwaysPreTouch", "false");
+
+        /* Check that parameters are gotten from third VM Option file which contains a mix of the options */
+        addVMParam("-showversion");
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_3));
+        addPropertiesToCheck("other.secret.data", "property");
+        addVMOptionsToCheck("UseGCOverheadLimit", "NewRatio");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+        outputShouldContain("interpreted mode");
+        checkProperty("other.secret.data", "qwerty");
+        checkProperty("property", "second");
+        checkVMOption("UseGCOverheadLimit", "false");
+        checkVMOption("NewRatio", "16");
+
+        /* Check that quotes are processed normally in VM Option file */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_QUOTE));
+        addPropertiesToCheck("my.quote.single", "my.quote.double", "javax.net.ssl.trustStorePassword");
+        addVMOptionsToCheck("ErrorFile");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+
+        checkProperty("my.quote.single", "Property in single quote. Here a double qoute\" Add some slashes \\/");
+        checkProperty("my.quote.double", "Double qoute. Include single '.");
+        checkProperty("javax.net.ssl.trustStorePassword", "data @+NEW");
+        checkVMOption("ErrorFile", "./my error file");
+
+        /* Check that quotes are processed normally in VM Option file. Pass max size file */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_QUOTE_MAX_SIZE));
+
+        addPropertiesToCheck("big");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+
+        checkProperty("big", String.format("%01016d", 9));
+
+        /*
+         * Verify that VM Option file accepts a file with 65 properties and with two options on separate
+         * lines and properties that use quotes a lot.
+         */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE));
+        for (int i = 1; i <= NUM_OF_PROP_IN_FILE_LOT_OF_OPTIONS_QUOTE; i++) {
+            addPropertiesToCheck(String.format("prop%02d", i));
+        }
+        addVMOptionsToCheck("MinHeapFreeRatio", "MaxHeapFreeRatio");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+
+        for (int i = 1; i <= NUM_OF_PROP_IN_FILE_LOT_OF_OPTIONS_QUOTE; i++) {
+            checkProperty(String.format("prop%02d", i), String.format("%02d", i));
+        }
+        checkVMOption("MinHeapFreeRatio", "7");
+        checkVMOption("MaxHeapFreeRatio", "96");
+
+        /*
+         * Verify that VM Option file accepts a file with maximum allowed size(1024 bytes)
+         */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITH_LONG_PROPERTY));
+        addPropertiesToCheck("very.very.long.property");
+
+        runJavaCheckExitValue(JVM_SUCCESS);
+        for (int i = 1; i < 249; i++) {
+            longProperty.append("long");
+        }
+        longProperty.append("l");
+        checkProperty("very.very.long.property", longProperty.toString());
+    }
+
+    private static ProcessBuilder prepareTestCase(int testCase) throws Exception {
+        ProcessBuilder pb;
+
+        Asserts.assertTrue(0 < testCase && testCase < 6, "testCase should be from 1 to 5");
+
+        addVMParam("-showversion");
+        addPropertiesToCheck("jto", "jo", "optfile_1", "shared.property");
+        addVMOptionsToCheck("MinHeapFreeRatio", "SurvivorRatio", "NewRatio");
+
+        if (testCase < 5) {
+            addVMParam("-XX:Flags=flags_file");
+            addProperty("shared.property", "command_line_before");
+            addProperty("clb", "unique_command_line_before");
+            addVMParam("-XX:MinHeapFreeRatio=7");
+        }
+
+        if (testCase < 4) {
+            addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1));
+        }
+
+        if (testCase < 3) {
+            addVMParam("-XX:MinHeapFreeRatio=9");
+            addProperty("shared.property", "command_line_after");
+            addProperty("cla", "unique_command_line_after");
+        }
+
+        /* Create ProcessBuilder after all setup is done to update environment variables */
+        pb = createProcessBuilder();
+
+        if (testCase < 2) {
+            updateEnvironment(pb, JAVA_OPTIONS, "-Dshared.property=somevalue -Djo=unique_java_options "
+                    + "-XX:MinHeapFreeRatio=18 -Dshared.property=java_options -XX:MinHeapFreeRatio=11");
+        }
+
+        if (testCase < 6) {
+            updateEnvironment(pb, JAVA_TOOL_OPTIONS, "-Dshared.property=qwerty -Djto=unique_java_tool_options "
+                    + "-XX:MinHeapFreeRatio=15 -Dshared.property=java_tool_options -XX:MinHeapFreeRatio=6");
+        }
+
+        return pb;
+    }
+
+    private static void testVMOptionsLastArgumentsWins() throws Exception {
+        ProcessBuilder pb;
+
+        /*
+         * "shared.property" property and "MinHeapFreeRatio" XX VM Option are defined
+         * in flags file, JAVA_TOOL_OPTIONS and _JAVA_OPTIONS environment variables,
+         * on command line before VM Option file, on command line after VM Option file
+         * and also in VM Option file. Verify that last argument wins. Also check
+         * unique properties and VM Options.
+         * Here is the order of options processing and last argument wins:
+         *    1) Flags file
+         *    2) JAVA_TOOL_OPTIONS environment variables
+         *    3) Pseudo command line from launcher
+         *    4) _JAVA_OPTIONS
+         * In every category arguments processed from left to right and from up to down
+         * and the last processed arguments wins, i.e. if argument is defined several
+         * times the value of argument will be equal to the last processed argument.
+         *
+         * "shared.property" property and "MinHeapFreeRatio" should be equal to the
+         * value from _JAVA_OPTIONS environment variable
+         */
+        pb = prepareTestCase(1);
+
+        runJavaCheckExitValue(pb, JVM_SUCCESS);
+
+        outputShouldContain("interpreted mode");
+        checkProperty("shared.property", "java_options");
+        checkVMOption("MinHeapFreeRatio", "11");
+        /* Each category defines its own properties */
+        checkProperty("jto", "unique_java_tool_options");
+        checkProperty("jo", "unique_java_options");
+        checkProperty("clb", "unique_command_line_before");
+        checkProperty("optfile_1", "option_file_1");
+        checkProperty("cla", "unique_command_line_after");
+        /* SurvivorRatio defined only in VM Option file */
+        checkVMOption("SurvivorRatio", "16");
+        /* NewRatio defined only in flags file */
+        checkVMOption("NewRatio", "5");
+
+        /*
+         * The same as previous but without _JAVA_OPTIONS environment variable.
+         * "shared.property" property and "MinHeapFreeRatio" should be equal to the
+         * value from pseudo command line after VM Option file
+         */
+        pb = prepareTestCase(2);
+
+        runJavaCheckExitValue(pb, JVM_SUCCESS);
+
+        outputShouldContain("interpreted mode");
+        checkProperty("shared.property", "command_line_after");
+        checkVMOption("MinHeapFreeRatio", "9");
+
+        /*
+         * The same as previous but without arguments in pseudo command line after
+         * VM Option file.
+         * "shared.property" property and "MinHeapFreeRatio" should be equal to the
+         * value from VM Option file.
+         */
+        pb = prepareTestCase(3);
+
+        runJavaCheckExitValue(pb, JVM_SUCCESS);
+
+        outputShouldContain("interpreted mode");
+        checkProperty("shared.property", "vmoptfile");
+        checkVMOption("MinHeapFreeRatio", "22");
+
+        /*
+         * The same as previous but without arguments in VM Option file.
+         * "shared.property" property and "MinHeapFreeRatio" should be equal to the
+         * value from pseudo command line.
+         */
+        pb = prepareTestCase(4);
+
+        runJavaCheckExitValue(pb, JVM_SUCCESS);
+
+        checkProperty("shared.property", "command_line_before");
+        checkVMOption("MinHeapFreeRatio", "7");
+
+        /*
+         * The same as previous but without arguments from pseudo command line.
+         * "shared.property" property and "MinHeapFreeRatio" should be equal to the
+         * value from JAVA_TOOL_OPTIONS environment variable.
+         */
+        pb = prepareTestCase(5);
+
+        runJavaCheckExitValue(pb, JVM_SUCCESS);
+
+        checkProperty("shared.property", "java_tool_options");
+        checkVMOption("MinHeapFreeRatio", "6");
+    }
+
+    private static void testVMOptionsInvalid() throws Exception {
+        ProcessBuilder pb;
+
+        /* Pass directory instead of file */
+        addVMOptionsFile(CURRENT_DIR);
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+
+        /* Pass not existing file */
+        addVMOptionsFile(getAbsolutePathFromSource(NOT_EXISTING_FILE));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Could not open options file");
+
+        /* Pass VM option file with bad option */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITH_BAD_OPTION));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Unrecognized VM option");
+
+        /* Pass VM option file with same VM option file option in it */
+        addVMOptionsFile(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE);
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("VM options file is only supported on the command line");
+
+        /* Pass VM option file with VM option file option in it */
+        addVMOptionsFile(VM_OPTION_FILE_WITH_VM_OPTION_FILE);
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("VM options file is only supported on the command line");
+
+        /* Pass VM option file with very long property(more than 1024 bytes) */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITH_VERY_LONG_PROPERTY));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Options file");
+        outputShouldContain("is larger than 1024 bytes");
+
+        /* Pass VM option file which is not accessible (without read permissions) */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Could not open options file");
+
+        /* Pass two VM option files */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1));
+        addVMOptionsFile(VM_OPTION_FILE_2);
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Only one VM Options file is supported on the command line");
+
+        /* Pass empty option file i.e. pass "-XX:VMOptionsFile=" */
+        addVMOptionsFile("");
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Could not open options file");
+
+        /* Pass VM option file with unmatched single quote */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_UNMATCHED_QUOTE_1));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Unmatched quote in");
+
+        /* Pass VM option file with unmatched double quote in X option */
+        addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_UNMATCHED_QUOTE_2));
+
+        runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1);
+        outputShouldContain("Unmatched quote in");
+    }
+
+    public static void main(String[] args) throws Exception {
+        /*
+         * Preparation before actual testing - create two VM Option files
+         * which contains VM Option file in it and copy other files to the
+         * current working folder
+         */
+        createOptionFiles();
+
+        testVMOptions(); /* Test VM Option file general functionality */
+        testVMOptionsLastArgumentsWins(); /* Verify that last argument wins */
+        testVMOptionsInvalid(); /* Test invalid VM Option file functionality */
+
+    }
+
+    public static class PrintPropertyAndOptions {
+
+        public static void main(String[] arguments) {
+            String property;
+            String vmOption;
+            for (String arg : arguments) {
+                if (arg.startsWith("property=")) {
+                    property = arg.substring(9);
+                    System.out.println("Property " + property + "=" + System.getProperty(property, "NOT DEFINED"));
+                } else if (arg.startsWith("vmoption=")) {
+                    vmOption = arg.substring(9);
+                    System.out.println("VM Option " + vmOption + "=" + (new DynamicVMOption(vmOption)).getValue());
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/flags_file	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,5 @@
++MaxFDLimit
+-AlwaysPreTouch
+MinHeapFreeRatio=3
+MaxHeapFreeRatio=89
+NewRatio=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionFILE_2	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,4 @@
+-XX:+UseGCOverheadLimit
+-XX:Flags=flags_file
+-Djavax.net.ssl.keyStorePassword=someVALUE123+
+-XX:NewRatio=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_1	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dshared.property=othervalue -XX:MinHeapFreeRatio=13 -Doptfile_1=option_file_1 -Xint -XX:SurvivorRatio=16 -Xminf0.22 -Dshared.property=vmoptfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_3	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,8 @@
+-Xcomp -Dproperty=first
+
+    -Xint
+-XX:+UseGCOverheadLimit
+
+  	-XX:NewRatio=4	-XX:-UseGCOverheadLimit	-Dproperty=second
+
+-Dother.secret.data=qwerty -XX:NewRatio=16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_bad_option	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dmy.property=user1 -XX:bad_option -Xint 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_long_property	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dvery.very.long.property=longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_lot_of_options_quote	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,66 @@
+-Dprop01='01'
+-Dprop02='02'
+-Dprop03='03'
+-Dprop04='04'
+-Dprop05='05'
+-D"pr"op06='06'
+-Dprop07='07'
+-Dprop08='08'
+-Dprop09="09"
+-Dprop"10=10"
+-Dprop11='11'
+'-Dprop12=12'
+-Dprop13='13'
+-Dprop14='14'
+-Dprop15='15'
+-Dprop16='16'
+-Dprop17='17'
+-Dprop18='18'
+-Dprop19='19'
+-Dprop20='20'
+-Dprop21='21'
+-Dprop22='22'
+-Dprop23='23'
+-Dpr'o'p24='24'
+-Dprop25='25'
+-Dprop26='26'
+-Dprop27='27'
+-Dprop28='28'
+-XX:MinHeapFreeRatio=7
+-D"prop29=29"
+-Dprop30='30'
+-Dprop31='31'
+-Dprop32="32"
+-Dprop33='33'
+-Dprop34='34'
+-Dprop35='35'
+'-Dpr'op36='36'
+-Dprop37='37'
+-Dprop38='38'
+-Dprop39='39'
+-Dprop40='40'
+-Dprop41='41'
+-Dprop42='42'
+-Dprop43='43'
+-Dprop44='44'
+-Dprop45='45'
+-D"prop46="'46'
+-Dprop47='47'
+-Dprop48='48'
+-Dprop49='49' 	-XX:MaxHeapFreeRatio=96
+"-"Dprop50='50'
+-Dprop51='51'
+-Dprop52='52'
+-Dprop53='53'
+-Dprop54='54'
+-Dprop55='55'
+-Dprop56='56'
+-Dprop57='57'
+-"D"prop58='58'
+-Dprop59='59'
+'-Dprop60=''60'
+-Dprop61='61'
+-Dprop62='62'
+-Dprop63='63'
+-Dprop64=64
+-Dprop65=65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_only_tabsandspaces	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,4 @@
+          	               	          	
+         	
+	
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_quote	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+'-Dmy.quote.single'='Property in single quote. Here a double qoute" Add some slashes \/' -D"my.quote.double"="Double qoute. Include single '." -'Xloggc':log"gc.log" -X"X:ErrorFile"=./my' error file' -Djavax.net.ssl.trustStorePassword='data @+NEW'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_quote_max_size	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dbig='00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009'
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_unmatched_quote_1	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dmy.quote.single='Unmatched single quote with embedded double " quote
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_unmatched_quote_2	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-"Xloggc:Unmatched quote in X option 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/VMOptionsFile/optionfile_very_long_property	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,1 @@
+-Dvery.very.long.property=longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/NMT/CommitOverlappingRegions.java	Mon Sep 28 15:05:02 2015 +0200
@@ -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
+ * @summary Test commits of overlapping regions of memory.
+ * @key nmt jcmd
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build   CommitOverlappingRegions
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail CommitOverlappingRegions
+ */
+
+import jdk.test.lib.*;
+import sun.hotspot.WhiteBox;
+
+public class CommitOverlappingRegions {
+    public static WhiteBox wb = WhiteBox.getWhiteBox();
+    public static void main(String args[]) throws Exception {
+        OutputAnalyzer output;
+        long size = 32 * 1024;
+        long addr;
+
+        String pid = Integer.toString(ProcessTools.getProcessId());
+        ProcessBuilder pb = new ProcessBuilder();
+
+        addr = wb.NMTReserveMemory(8*size);        // [                ]
+        pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+        // Test output before commits
+        output = new OutputAnalyzer(pb.start());
+        output.shouldContain("(reserved=256KB, committed=0KB)");
+
+        // Commit regions 1 and 2, then test output.
+        wb.NMTCommitMemory(addr + 0*size, 3*size); // [       ]
+        wb.NMTCommitMemory(addr + 4*size, 3*size); //           [      ]
+
+        output = new OutputAnalyzer(pb.start());
+        output.shouldContain("(reserved=256KB, committed=192KB)");
+
+        // Commit the final region which overlaps partially with both regions.
+        wb.NMTCommitMemory(addr + 2*size, 3*size); //     [        ]
+
+        output = new OutputAnalyzer(pb.start());
+        output.getOutput();
+        output.shouldContain("(reserved=256KB, committed=224KB)");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/logging/TestBasicLogOutput.java	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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 TestBasicLogOutput
+ * @summary Ensure logging can be enabled and successfully prints to stdout.
+ * @library /testlibrary
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestBasicLogOutput {
+
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:all=trace", "-version");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("[logging]"); // expected tag(s)
+        output.shouldContain("Log configuration fully initialized."); // expected message
+        output.shouldHaveExitValue(0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java	Mon Sep 28 15:05:02 2015 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.apps.LingeredAppWithDeadlock;
+
+import jdk.test.lib.Utils;
+import jdk.test.lib.Platform;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+/*
+ * @test
+ * @summary Test deadlock detection
+ * @library /../../test/lib/share/classes
+ * @library /testlibrary
+ * @modules java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.apps.*
+ * @build DeadlockDetectionTest
+ * @run main DeadlockDetectionTest
+ */
+
+public class DeadlockDetectionTest {
+
+    private static LingeredAppWithDeadlock theApp = null;
+    private static ProcessBuilder processBuilder = new ProcessBuilder();
+
+    private static OutputAnalyzer jstack(String... toolArgs) throws Exception {
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+        launcher.addToolArg("jstack");
+        if (toolArgs != null) {
+            for (String toolArg : toolArgs) {
+                launcher.addToolArg(toolArg);
+            }
+        }
+
+        processBuilder.command(launcher.getCommand());
+        System.out.println(processBuilder.command().stream().collect(Collectors.joining(" ")));
+        OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+        System.out.println(output.getOutput());
+
+        return output;
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting DeadlockDetectionTest");
+
+        if (!Platform.shouldSAAttach()) {
+            // Silently skip the test if we don't have enough permissions to attach
+            // Not all conditions checked by function is relevant to SA but it's worth
+            // to check
+            System.err.println("Error! Insufficient permissions to attach.");
+            return;
+        }
+
+
+        if (!LingeredApp.isLastModifiedWorking()) {
+            // Exact behaviour of the test depends on operating system and the test nature,
+            // so just print the warning and continue
+            System.err.println("Warning! Last modified time doesn't work.");
+        }
+
+        try {
+            List<String> vmArgs = new ArrayList<String>();
+            vmArgs.add("-XX:+UsePerfData");
+            vmArgs.addAll(Utils.getVmOptions());
+
+            theApp = new LingeredAppWithDeadlock();
+            LingeredApp.startApp(vmArgs, theApp);
+            OutputAnalyzer output = jstack("--pid", Long.toString(theApp.getPid()));
+            System.out.println(output.getOutput());
+
+            if (output.getExitValue() == 3) {
+                System.out.println("Test can't run for some reason. Skipping");
+            }
+            else {
+                output.shouldHaveExitValue(0);
+                output.shouldContain("Found a total of 1 deadlock.");
+            }
+
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+    }
+}