changeset 3365:cd3a8ab0352b

Merge
author zgu
date Thu, 24 May 2012 20:04:07 -0400
parents df84b4a3ebcb cee14a6fc5ac
children 17be2328b50b
files
diffstat 40 files changed, 580 insertions(+), 318 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu May 24 13:37:47 2012 +0200
+++ b/.hgtags	Thu May 24 20:04:07 2012 -0400
@@ -242,4 +242,9 @@
 f621660a297baa48fab9dca28e99d318826e8304 jdk8-b35
 dff6e3459210f8dd0430b9b03ccc99280560da30 hs24-b08
 50b4400ca1ecb2ac2fde35f5e53ec8f04b86be7f jdk8-b36
+bfcf92bfefb82da00f7fdbf0d9273feaa0a9456d jdk8-b37
 7d5ec8bf38d1b12e0e09ec381f10976b8beede3b hs24-b09
+637c3f5f068f88fb9ec9c5867341cf59fd5ebedc jdk8-b38
+73147e6c48813b5fee904aa33f79a77103250ff4 hs24-b10
+96a403721094ecdaf6a1f4f52ebd0a82e07df199 jdk8-b39
+14b0e07ab9a6fa1662414496b7e07ac8450cf517 hs24-b11
--- a/make/hotspot_version	Thu May 24 13:37:47 2012 +0200
+++ b/make/hotspot_version	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 # 
-# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -31,11 +31,11 @@
 #
 
 # Don't put quotes (fail windows build).
-HOTSPOT_VM_COPYRIGHT=Copyright 2011
+HOTSPOT_VM_COPYRIGHT=Copyright 2012
 
 HS_MAJOR_VER=24
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=10
+HS_BUILD_NUMBER=12
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/linux/makefiles/vm.make	Thu May 24 13:37:47 2012 +0200
+++ b/make/linux/makefiles/vm.make	Thu May 24 20:04:07 2012 -0400
@@ -102,9 +102,11 @@
 # a time and date. 
 vm_version.o: CXXFLAGS += ${JRE_VERSION}
 
-ifndef JAVASE_EMBEDDED
+ifndef JAVASE_EMBEDDED 
+ifneq (${ARCH},arm)
 CFLAGS += -DINCLUDE_TRACE
 endif
+endif
 
 # CFLAGS_WARN holds compiler options to suppress/enable warnings.
 CFLAGS += $(CFLAGS_WARN/BYFILE)
@@ -153,11 +155,13 @@
 SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
 SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
 
-ifndef JAVASE_EMBEDDED
+ifndef JAVASE_EMBEDDED 
+ifneq (${ARCH},arm)
 SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
   find $(HS_ALT_SRC)/share/vm/jfr -type d; \
   fi)
 endif
+endif
 
 CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
 CORE_PATHS+=$(GENERATED)/jvmtifiles
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -238,9 +238,12 @@
 
   Register result = dst->as_register();
   {
-    // Get a pointer to the first character of string0 in tmp0 and get string0.count in str0
-    // Get a pointer to the first character of string1 in tmp1 and get string1.count in str1
-    // Also, get string0.count-string1.count in o7 and get the condition code set
+    // Get a pointer to the first character of string0 in tmp0
+    //   and get string0.length() in str0
+    // Get a pointer to the first character of string1 in tmp1
+    //   and get string1.length() in str1
+    // Also, get string0.length()-string1.length() in
+    //   o7 and get the condition code set
     // Note: some instructions have been hoisted for better instruction scheduling
 
     Register tmp0 = L0;
@@ -248,27 +251,40 @@
     Register tmp2 = L2;
 
     int  value_offset = java_lang_String:: value_offset_in_bytes(); // char array
-    int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
-    int  count_offset = java_lang_String:: count_offset_in_bytes();
-
-    __ load_heap_oop(str0, value_offset, tmp0);
-    __ ld(str0, offset_offset, tmp2);
-    __ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
-    __ ld(str0, count_offset, str0);
-    __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
+    if (java_lang_String::has_offset_field()) {
+      int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
+      int  count_offset = java_lang_String:: count_offset_in_bytes();
+      __ load_heap_oop(str0, value_offset, tmp0);
+      __ ld(str0, offset_offset, tmp2);
+      __ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
+      __ ld(str0, count_offset, str0);
+      __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
+    } else {
+      __ load_heap_oop(str0, value_offset, tmp1);
+      __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
+      __ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
+    }
 
     // str1 may be null
     add_debug_info_for_null_check_here(info);
 
-    __ load_heap_oop(str1, value_offset, tmp1);
-    __ add(tmp0, tmp2, tmp0);
-
-    __ ld(str1, offset_offset, tmp2);
-    __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
-    __ ld(str1, count_offset, str1);
-    __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
+    if (java_lang_String::has_offset_field()) {
+      int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
+      int  count_offset = java_lang_String:: count_offset_in_bytes();
+      __ load_heap_oop(str1, value_offset, tmp1);
+      __ add(tmp0, tmp2, tmp0);
+
+      __ ld(str1, offset_offset, tmp2);
+      __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
+      __ ld(str1, count_offset, str1);
+      __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
+      __ add(tmp1, tmp2, tmp1);
+    } else {
+      __ load_heap_oop(str1, value_offset, tmp2);
+      __ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
+      __ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
+    }
     __ subcc(str0, str1, O7);
-    __ add(tmp1, tmp2, tmp1);
   }
 
   {
@@ -302,7 +318,7 @@
     // Shift base0 and base1 to the end of the arrays, negate limit
     __ add(base0, limit, base0);
     __ add(base1, limit, base1);
-    __ neg(limit);  // limit = -min{string0.count, strin1.count}
+    __ neg(limit);  // limit = -min{string0.length(), string1.length()}
 
     __ lduh(base0, limit, chr0);
     __ bind(Lloop);
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -505,19 +505,28 @@
 
   // Get addresses of first characters from both Strings
   __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
-  __ movptr       (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
-  __ lea          (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
-
+  if (java_lang_String::has_offset_field()) {
+    __ movptr     (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
+    __ movl       (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
+    __ lea        (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+  } else {
+    __ movl       (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes()));
+    __ lea        (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+  }
 
   // rbx, may be NULL
   add_debug_info_for_null_check_here(info);
   __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
-  __ movptr       (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
-  __ lea          (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+  if (java_lang_String::has_offset_field()) {
+    __ movptr     (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
+    __ movl       (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
+    __ lea        (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+  } else {
+    __ movl       (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
+    __ lea        (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+  }
 
   // compute minimum length (in rax) and difference of lengths (on top of stack)
-  __ movl  (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
-  __ movl  (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
   __ mov   (rcx, rbx);
   __ subptr(rbx, rax); // subtract lengths
   __ push  (rbx);      // result
--- a/src/share/vm/classfile/javaClasses.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -143,7 +143,27 @@
 }
 
 
+int java_lang_String::value_offset  = 0;
+int java_lang_String::offset_offset = 0;
+int java_lang_String::count_offset  = 0;
+int java_lang_String::hash_offset   = 0;
+
+bool java_lang_String::initialized  = false;
+
+void java_lang_String::compute_offsets() {
+  assert(!initialized, "offsets should be initialized only once");
+
+  klassOop k = SystemDictionary::String_klass();
+  compute_offset(value_offset,           k, vmSymbols::value_name(),  vmSymbols::char_array_signature());
+  compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature());
+  compute_optional_offset(count_offset,  k, vmSymbols::count_name(),  vmSymbols::int_signature());
+  compute_optional_offset(hash_offset,   k, vmSymbols::hash_name(),   vmSymbols::int_signature());
+
+  initialized = true;
+}
+
 Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
+  assert(initialized, "Must be initialized");
   // Create the String object first, so there's a chance that the String
   // and the char array it points to end up in the same cache line.
   oop obj;
@@ -2837,10 +2857,6 @@
 
 
 
-int java_lang_String::value_offset;
-int java_lang_String::offset_offset;
-int java_lang_String::count_offset;
-int java_lang_String::hash_offset;
 int java_lang_Class::_klass_offset;
 int java_lang_Class::_array_klass_offset;
 int java_lang_Class::_resolved_constructor_offset;
@@ -3000,12 +3016,6 @@
   const int x = heapOopSize;
   const int header = instanceOopDesc::base_offset_in_bytes();
 
-  // Do the String Class
-  java_lang_String::value_offset  = java_lang_String::hc_value_offset  * x + header;
-  java_lang_String::offset_offset = java_lang_String::hc_offset_offset * x + header;
-  java_lang_String::count_offset  = java_lang_String::offset_offset + sizeof (jint);
-  java_lang_String::hash_offset   = java_lang_String::count_offset + sizeof (jint);
-
   // Throwable Class
   java_lang_Throwable::backtrace_offset  = java_lang_Throwable::hc_backtrace_offset  * x + header;
   java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
@@ -3200,9 +3210,13 @@
   // java.lang.String
 
   CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C");
-  CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
-  CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
-  CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
+  if (java_lang_String::has_offset_field()) {
+    CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
+    CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
+  }
+  if (java_lang_String::has_hash_field()) {
+    CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
+  }
 
   // java.lang.Class
 
--- a/src/share/vm/classfile/javaClasses.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,26 +52,36 @@
 
 class java_lang_String : AllStatic {
  private:
-  enum {
-    hc_value_offset  = 0,
-    hc_offset_offset = 1
-    //hc_count_offset = 2  -- not a word-scaled offset
-    //hc_hash_offset  = 3  -- not a word-scaled offset
-  };
-
   static int value_offset;
   static int offset_offset;
   static int count_offset;
   static int hash_offset;
 
+  static bool initialized;
+
   static Handle basic_create(int length, bool tenured, TRAPS);
   static Handle basic_create_from_unicode(jchar* unicode, int length, bool tenured, TRAPS);
 
-  static void set_value( oop string, typeArrayOop buffer) { string->obj_field_put(value_offset,  (oop)buffer); }
-  static void set_offset(oop string, int offset)          { string->int_field_put(offset_offset, offset); }
-  static void set_count( oop string, int count)           { string->int_field_put(count_offset,  count);  }
+  static void set_value( oop string, typeArrayOop buffer) {
+    assert(initialized, "Must be initialized");
+    string->obj_field_put(value_offset,  (oop)buffer);
+  }
+  static void set_offset(oop string, int offset) {
+    assert(initialized, "Must be initialized");
+    if (offset_offset > 0) {
+      string->int_field_put(offset_offset, offset);
+    }
+  }
+  static void set_count( oop string, int count) {
+    assert(initialized, "Must be initialized");
+    if (count_offset > 0) {
+      string->int_field_put(count_offset,  count);
+    }
+  }
 
  public:
+  static void compute_offsets();
+
   // Instance creation
   static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
   static Handle create_tenured_from_unicode(jchar* unicode, int len, TRAPS);
@@ -82,23 +92,61 @@
   static Handle create_from_platform_dependent_str(const char* str, TRAPS);
   static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
 
-  static int value_offset_in_bytes()  { return value_offset;  }
-  static int count_offset_in_bytes()  { return count_offset;  }
-  static int offset_offset_in_bytes() { return offset_offset; }
-  static int hash_offset_in_bytes()   { return hash_offset;   }
+  static bool has_offset_field()  {
+    assert(initialized, "Must be initialized");
+    return (offset_offset > 0);
+  }
+
+  static bool has_count_field()  {
+    assert(initialized, "Must be initialized");
+    return (count_offset > 0);
+  }
+
+  static bool has_hash_field()  {
+    assert(initialized, "Must be initialized");
+    return (hash_offset > 0);
+  }
+
+  static int value_offset_in_bytes()  {
+    assert(initialized && (value_offset > 0), "Must be initialized");
+    return value_offset;
+  }
+  static int count_offset_in_bytes()  {
+    assert(initialized && (count_offset > 0), "Must be initialized");
+    return count_offset;
+  }
+  static int offset_offset_in_bytes() {
+    assert(initialized && (offset_offset > 0), "Must be initialized");
+    return offset_offset;
+  }
+  static int hash_offset_in_bytes()   {
+    assert(initialized && (hash_offset > 0), "Must be initialized");
+    return hash_offset;
+  }
 
   // Accessors
   static typeArrayOop value(oop java_string) {
+    assert(initialized && (value_offset > 0), "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
     return (typeArrayOop) java_string->obj_field(value_offset);
   }
   static int offset(oop java_string) {
+    assert(initialized, "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
-    return java_string->int_field(offset_offset);
+    if (offset_offset > 0) {
+      return java_string->int_field(offset_offset);
+    } else {
+      return 0;
+    }
   }
   static int length(oop java_string) {
+    assert(initialized, "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
-    return java_string->int_field(count_offset);
+    if (count_offset > 0) {
+      return java_string->int_field(count_offset);
+    } else {
+      return ((typeArrayOop)java_string->obj_field(value_offset))->length();
+    }
   }
   static int utf8_length(oop java_string);
 
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1971,6 +1971,9 @@
   // first do Object, String, Class
   initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
 
+  // Calculate offsets for String and Class classes since they are loaded and
+  // can be used after this point.
+  java_lang_String::compute_offsets();
   java_lang_Class::compute_offsets();
 
   // Fixup mirrors for classes loaded before java.lang.Class.
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu May 24 20:04:07 2012 -0400
@@ -340,6 +340,9 @@
   template(park_event_name,                           "nativeParkEventPointer")                   \
   template(cache_field_name,                          "cache")                                    \
   template(value_name,                                "value")                                    \
+  template(offset_name,                               "offset")                                   \
+  template(count_name,                                "count")                                    \
+  template(hash_name,                                 "hash")                                     \
   template(frontCacheEnabled_name,                    "frontCacheEnabled")                        \
   template(stringCacheEnabled_name,                   "stringCacheEnabled")                       \
   template(numberOfLeadingZeros_name,                 "numberOfLeadingZeros")                     \
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu May 24 20:04:07 2012 -0400
@@ -6332,10 +6332,10 @@
   )
 }
 
-void CMSCollector::do_CMS_operation(CMS_op_type op) {
+void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-  TraceTime t("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
+  TraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
   TraceCollectorStats tcs(counters());
 
   switch (op) {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu May 24 20:04:07 2012 -0400
@@ -717,7 +717,7 @@
     CMS_op_checkpointRootsFinal
   };
 
-  void do_CMS_operation(CMS_op_type op);
+  void do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause);
   bool stop_world_and_do(CMS_op_type op);
 
   OopTaskQueueSet* task_queues() { return _task_queues; }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp	Thu May 24 20:04:07 2012 -0400
@@ -146,7 +146,7 @@
   VM_CMS_Operation::verify_before_gc();
 
   IsGCActiveMark x; // stop-world GC active
-  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial);
+  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());
 
   VM_CMS_Operation::verify_after_gc();
 #ifndef USDT2
@@ -178,7 +178,7 @@
   VM_CMS_Operation::verify_before_gc();
 
   IsGCActiveMark x; // stop-world GC active
-  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);
+  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause());
 
   VM_CMS_Operation::verify_after_gc();
 #ifndef USDT2
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1252,10 +1252,7 @@
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
-    char verbose_str[128];
-    sprintf(verbose_str, "Full GC (%s)", GCCause::to_string(gc_cause()));
-    TraceTime t(verbose_str, G1Log::fine(), true, gclog_or_tty);
-
+    TraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, gclog_or_tty);
     TraceCollectorStats tcs(g1mm()->full_collection_counters());
     TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
 
@@ -3600,12 +3597,10 @@
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
-    char verbose_str[128];
-    sprintf(verbose_str, "GC pause (%s) (%s)%s",
-      GCCause::to_string(gc_cause()),
-      g1_policy()->gcs_are_young() ? "young" : "mixed",
-      g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
-    TraceTime t(verbose_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
+    GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
+      .append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)")
+      .append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
+    TraceTime t(gc_cause_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
     TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
@@ -5502,7 +5497,7 @@
   if (evacuation_failed()) {
     remove_self_forwarding_pointers();
     if (G1Log::finer()) {
-      gclog_or_tty->print(" (to-space overflow)");
+      gclog_or_tty->print(" (to-space exhausted)");
     } else if (G1Log::fine()) {
       gclog_or_tty->print("--");
     }
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu May 24 20:04:07 2012 -0400
@@ -886,9 +886,8 @@
                                                       size_t start_used) {
   if (G1Log::finer()) {
     gclog_or_tty->stamp(PrintGCTimeStamps);
-    gclog_or_tty->print("[GC pause (%s) (%s)",
-      GCCause::to_string(_g1->gc_cause()),
-      gcs_are_young() ? "young" : "mixed");
+    gclog_or_tty->print("[%s", (const char*)GCCauseString("GC pause", _g1->gc_cause())
+      .append(gcs_are_young() ? " (young)" : " (mixed)"));
   }
 
   // We only need to do this here as the policy will only be applied
@@ -1010,7 +1009,8 @@
 
 void G1CollectorPolicy::print_par_stats(int level,
                                         const char* str,
-                                        double* data) {
+                                        double* data,
+                                        bool showDecimals) {
   double min = data[0], max = data[0];
   double total = 0.0;
   LineBuffer buf(level);
@@ -1023,7 +1023,11 @@
       max = val;
     total += val;
     if (G1Log::finest()) {
-      buf.append("  %.1lf", val);
+      if (showDecimals) {
+        buf.append("  %.1lf", val);
+      } else {
+        buf.append("  %d", (int)val);
+      }
     }
   }
 
@@ -1031,36 +1035,26 @@
     buf.append_and_print_cr("");
   }
   double avg = total / (double) no_of_gc_threads();
-  buf.append_and_print_cr(" Avg: %.1lf Min: %.1lf Max: %.1lf Diff: %.1lf]",
-    avg, min, max, max - min);
-}
-
-void G1CollectorPolicy::print_par_sizes(int level,
-                                        const char* str,
-                                        double* data) {
-  double min = data[0], max = data[0];
-  double total = 0.0;
-  LineBuffer buf(level);
-  buf.append("[%s :", str);
-  for (uint i = 0; i < no_of_gc_threads(); ++i) {
-    double val = data[i];
-    if (val < min)
-      min = val;
-    if (val > max)
-      max = val;
-    total += val;
-    buf.append(" %d", (int) val);
+  if (showDecimals) {
+    buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]",
+      min, avg, max, max - min, total);
+  } else {
+    buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]",
+      (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total);
   }
-  buf.append_and_print_cr("");
-  double avg = total / (double) no_of_gc_threads();
-  buf.append_and_print_cr(" Sum: %d, Avg: %d, Min: %d, Max: %d, Diff: %d]",
-    (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
 }
 
 void G1CollectorPolicy::print_stats(int level,
                                     const char* str,
                                     double value) {
-  LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value);
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
+}
+
+void G1CollectorPolicy::print_stats(int level,
+                                    const char* str,
+                                    double value,
+                                    int workers) {
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
 }
 
 void G1CollectorPolicy::print_stats(int level,
@@ -1373,7 +1367,7 @@
       print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
     }
     if (parallel) {
-      print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
+      print_stats(1, "Parallel Time", _cur_collection_par_time_ms, no_of_gc_threads);
       print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
       print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
       if (print_marking_info) {
@@ -1381,13 +1375,15 @@
       }
       print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
       if (G1Log::finest()) {
-        print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
+        print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers,
+          false /* showDecimals */);
       }
       print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
       print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
       print_par_stats(2, "Termination", _par_last_termination_times_ms);
       if (G1Log::finest()) {
-        print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
+        print_par_stats(3, "Termination Attempts", _par_last_termination_attempts,
+          false /* showDecimals */);
       }
 
       for (int i = 0; i < _parallel_gc_threads; i++) {
@@ -1601,9 +1597,9 @@
   _collectionSetChooser->verify();
 }
 
-#define EXT_SIZE_FORMAT "%d%s"
+#define EXT_SIZE_FORMAT "%.1f%s"
 #define EXT_SIZE_PARAMS(bytes)                                  \
-  byte_size_in_proper_unit((bytes)),                            \
+  byte_size_in_proper_unit((double)(bytes)),                    \
   proper_unit_for_byte_size((bytes))
 
 void G1CollectorPolicy::print_heap_transition() {
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu May 24 20:04:07 2012 -0400
@@ -552,10 +552,10 @@
 
 private:
   void print_stats(int level, const char* str, double value);
+  void print_stats(int level, const char* str, double value, int workers);
   void print_stats(int level, const char* str, int value);
 
-  void print_par_stats(int level, const char* str, double* data);
-  void print_par_sizes(int level, const char* str, double* data);
+  void print_par_stats(int level, const char* str, double* data, bool showDecimals = true);
 
   void check_other_times(int level,
                          NumberSeq* other_times_ms,
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Thu May 24 20:04:07 2012 -0400
@@ -42,6 +42,7 @@
 
 void VM_G1CollectForAllocation::doit() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  GCCauseSetter x(g1h, _gc_cause);
   _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
   assert(_result == NULL || _pause_succeeded,
          "if we get back a result, the pause should have succeeded");
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu May 24 20:04:07 2012 -0400
@@ -916,7 +916,7 @@
     size_policy->minor_collection_begin();
   }
 
-  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Thu May 24 20:04:07 2012 -0400
@@ -160,16 +160,10 @@
 
   {
     HandleMark hm;
-    const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
-    // This is useful for debugging but don't change the output the
-    // the customer sees.
-    const char* gc_cause_str = "Full GC";
-    if (is_system_gc && PrintGCDetails) {
-      gc_cause_str = "Full GC (System)";
-    }
+
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu May 24 20:04:07 2012 -0400
@@ -2047,17 +2047,9 @@
     gc_task_manager()->task_idle_workers();
     heap->set_par_threads(gc_task_manager()->active_workers());
 
-    const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
-
-    // This is useful for debugging but don't change the output the
-    // the customer sees.
-    const char* gc_cause_str = "Full GC";
-    if (is_system_gc && PrintGCDetails) {
-      gc_cause_str = "Full GC (System)";
-    }
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
@@ -2090,7 +2082,8 @@
     }
 #endif  // #ifndef PRODUCT
 
-    bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc;
+    bool max_on_system_gc = UseMaximumCompactionOnSystemGC
+      && gc_cause == GCCause::_java_lang_system_gc;
     summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
 
     COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Thu May 24 20:04:07 2012 -0400
@@ -325,7 +325,7 @@
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(false /* not full GC */,gc_cause);
 
--- a/src/share/vm/gc_implementation/shared/gcUtil.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/shared/gcUtil.cpp	Thu May 24 20:04:07 2012 -0400
@@ -31,9 +31,15 @@
                                                         float average) {
   // We smooth the samples by not using weight() directly until we've
   // had enough data to make it meaningful. We'd like the first weight
-  // used to be 1, the second to be 1/2, etc until we have 100/weight
-  // samples.
-  unsigned count_weight = 100/count();
+  // used to be 1, the second to be 1/2, etc until we have
+  // OLD_THRESHOLD/weight samples.
+  unsigned count_weight = 0;
+
+  // Avoid division by zero if the counter wraps (7158457)
+  if (!is_old()) {
+    count_weight = OLD_THRESHOLD/count();
+  }
+
   unsigned adaptive_weight = (MAX2(weight(), count_weight));
 
   float new_avg = exp_avg(average, new_sample, adaptive_weight);
@@ -43,8 +49,6 @@
 
 void AdaptiveWeightedAverage::sample(float new_sample) {
   increment_count();
-  assert(count() != 0,
-         "Wraparound -- history would be incorrectly discarded");
 
   // Compute the new weighted average
   float new_avg = compute_adaptive_average(new_sample, average());
--- a/src/share/vm/gc_implementation/shared/gcUtil.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_implementation/shared/gcUtil.hpp	Thu May 24 20:04:07 2012 -0400
@@ -50,11 +50,20 @@
   unsigned         _weight;         // The weight used to smooth the averages
                                     //   A higher weight favors the most
                                     //   recent data.
+  bool             _is_old;         // Has enough historical data
+
+  const static unsigned OLD_THRESHOLD = 100;
 
  protected:
   float            _last_sample;    // The last value sampled.
 
-  void  increment_count()       { _sample_count++;       }
+  void  increment_count() {
+    _sample_count++;
+    if (!_is_old && _sample_count > OLD_THRESHOLD) {
+      _is_old = true;
+    }
+  }
+
   void  set_average(float avg)  { _average = avg;        }
 
   // Helper function, computes an adaptive weighted average
@@ -64,13 +73,15 @@
  public:
   // Input weight must be between 0 and 100
   AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) :
-    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0) {
+    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0),
+    _is_old(false) {
   }
 
   void clear() {
     _average = 0;
     _sample_count = 0;
     _last_sample = 0;
+    _is_old = false;
   }
 
   // Useful for modifying static structures after startup.
@@ -84,7 +95,8 @@
   float    average() const       { return _average;       }
   unsigned weight()  const       { return _weight;        }
   unsigned count()   const       { return _sample_count;  }
-  float    last_sample() const   { return _last_sample; }
+  float    last_sample() const   { return _last_sample;   }
+  bool     is_old()  const       { return _is_old;        }
 
   // Update data with a new sample.
   void sample(float new_sample);
--- a/src/share/vm/gc_interface/gcCause.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/gc_interface/gcCause.hpp	Thu May 24 20:04:07 2012 -0400
@@ -88,4 +88,36 @@
   static const char* to_string(GCCause::Cause cause);
 };
 
+// Helper class for doing logging that includes the GC Cause
+// as a string.
+class GCCauseString : StackObj {
+ private:
+   static const int _length = 128;
+   char _buffer[_length];
+   int _position;
+
+ public:
+   GCCauseString(const char* prefix, GCCause::Cause cause) {
+     if (PrintGCCause) {
+      _position = jio_snprintf(_buffer, _length, "%s (%s)", prefix, GCCause::to_string(cause));
+     } else {
+      _position = jio_snprintf(_buffer, _length, "%s", prefix);
+     }
+     assert(_position >= 0 && _position <= _length,
+       err_msg("Need to increase the buffer size in GCCauseString? %d", _position));
+   }
+
+   GCCauseString& append(const char* str) {
+     int res = jio_snprintf(_buffer + _position, _length - _position, "%s", str);
+     _position += res;
+     assert(res >= 0 && _position <= _length,
+       err_msg("Need to increase the buffer size in GCCauseString? %d", res));
+     return *this;
+   }
+
+   operator const char*() {
+     return _buffer;
+   }
+};
+
 #endif // SHARE_VM_GC_INTERFACE_GCCAUSE_HPP
--- a/src/share/vm/memory/defNewGeneration.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/defNewGeneration.cpp	Thu May 24 20:04:07 2012 -0400
@@ -548,7 +548,7 @@
 
   init_assuming_no_promotion_failure();
 
-  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
--- a/src/share/vm/memory/dump.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/dump.cpp	Thu May 24 20:04:07 2012 -0400
@@ -78,8 +78,8 @@
   void do_oop(oop* p) {
     if (p != NULL) {
       oop obj = *p;
-      if (obj->klass() == SystemDictionary::String_klass()) {
-
+      if (obj->klass() == SystemDictionary::String_klass() &&
+          java_lang_String::has_hash_field()) {
         int hash = java_lang_String::hash_string(obj);
         obj->int_field_put(hash_offset, hash);
       }
--- a/src/share/vm/memory/genCollectedHeap.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Thu May 24 20:04:07 2012 -0400
@@ -480,26 +480,15 @@
   const size_t perm_prev_used = perm_gen()->used();
 
   print_heap_before_gc();
-  if (Verbose) {
-    gclog_or_tty->print_cr("GC Cause: %s", GCCause::to_string(gc_cause()));
-  }
 
   {
     FlagSetting fl(_is_gc_active, true);
 
     bool complete = full && (max_level == (n_gens()-1));
-    const char* gc_cause_str = "GC ";
-    if (complete) {
-      GCCause::Cause cause = gc_cause();
-      if (cause == GCCause::_java_lang_system_gc) {
-        gc_cause_str = "Full GC (System) ";
-      } else {
-        gc_cause_str = "Full GC ";
-      }
-    }
+    const char* gc_cause_prefix = complete ? "Full GC" : "GC";
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t(gc_cause_str, PrintGCDetails, false, gclog_or_tty);
+    TraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, gclog_or_tty);
 
     gc_prologue(complete);
     increment_total_collections(complete);
--- a/src/share/vm/memory/genMarkSweep.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/genMarkSweep.cpp	Thu May 24 20:04:07 2012 -0400
@@ -76,7 +76,7 @@
   _ref_processor = rp;
   rp->setup_policy(clear_all_softrefs);
 
-  TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
 
   // When collecting the permanent generation methodOops may be moving,
   // so we either have to flush all bcp data or convert it into bci.
--- a/src/share/vm/memory/space.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/space.hpp	Thu May 24 20:04:07 2012 -0400
@@ -880,10 +880,17 @@
   void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
   // iterates on objects up to the safe limit
   HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
-  inline HeapWord* concurrent_iteration_safe_limit();
+  HeapWord* concurrent_iteration_safe_limit() {
+    assert(_concurrent_iteration_safe_limit <= top(),
+           "_concurrent_iteration_safe_limit update missed");
+    return _concurrent_iteration_safe_limit;
+  }
   // changes the safe limit, all objects from bottom() to the new
   // limit should be properly initialized
-  inline void set_concurrent_iteration_safe_limit(HeapWord* new_limit);
+  void set_concurrent_iteration_safe_limit(HeapWord* new_limit) {
+    assert(new_limit <= top(), "uninitialized objects in the safe range");
+    _concurrent_iteration_safe_limit = new_limit;
+  }
 
 #ifndef SERIALGC
   // In support of parallel oop_iterate.
--- a/src/share/vm/memory/space.inline.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/memory/space.inline.hpp	Thu May 24 20:04:07 2012 -0400
@@ -67,17 +67,4 @@
   return _offsets.block_start(p);
 }
 
-inline HeapWord* ContiguousSpace::concurrent_iteration_safe_limit()
-{
-  assert(_concurrent_iteration_safe_limit <= top(),
-         "_concurrent_iteration_safe_limit update missed");
-  return _concurrent_iteration_safe_limit;
-}
-
-inline void ContiguousSpace::set_concurrent_iteration_safe_limit(HeapWord* new_limit)
-{
-  assert(new_limit <= top(), "uninitialized objects in the safe range");
-  _concurrent_iteration_safe_limit = new_limit;
-}
-
 #endif // SHARE_VM_MEMORY_SPACE_INLINE_HPP
--- a/src/share/vm/opto/graphKit.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/opto/graphKit.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3748,3 +3748,81 @@
   final_sync(ideal);
 }
 #undef __
+
+
+
+Node* GraphKit::load_String_offset(Node* ctrl, Node* str) {
+  if (java_lang_String::has_offset_field()) {
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                       false, NULL, 0);
+    const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
+    int offset_field_idx = C->get_alias_index(offset_field_type);
+    return make_load(ctrl,
+                     basic_plus_adr(str, str, offset_offset),
+                     TypeInt::INT, T_INT, offset_field_idx);
+  } else {
+    return intcon(0);
+  }
+}
+
+Node* GraphKit::load_String_length(Node* ctrl, Node* str) {
+  if (java_lang_String::has_count_field()) {
+    int count_offset = java_lang_String::count_offset_in_bytes();
+    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                       false, NULL, 0);
+    const TypePtr* count_field_type = string_type->add_offset(count_offset);
+    int count_field_idx = C->get_alias_index(count_field_type);
+    return make_load(ctrl,
+                     basic_plus_adr(str, str, count_offset),
+                     TypeInt::INT, T_INT, count_field_idx);
+  } else {
+    return load_array_length(load_String_value(ctrl, str));
+  }
+}
+
+Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
+  int value_offset = java_lang_String::value_offset_in_bytes();
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+  const TypePtr* value_field_type = string_type->add_offset(value_offset);
+  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
+                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
+                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
+  int value_field_idx = C->get_alias_index(value_field_type);
+  return make_load(ctrl, basic_plus_adr(str, str, value_offset),
+                   value_type, T_OBJECT, value_field_idx);
+}
+
+void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
+  int offset_offset = java_lang_String::offset_offset_in_bytes();
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+  const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
+  int offset_field_idx = C->get_alias_index(offset_field_type);
+  store_to_memory(ctrl, basic_plus_adr(str, offset_offset),
+                  value, T_INT, offset_field_idx);
+}
+
+void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
+  int value_offset = java_lang_String::value_offset_in_bytes();
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+  const TypePtr* value_field_type = string_type->add_offset(value_offset);
+  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
+                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
+                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
+  int value_field_idx = C->get_alias_index(value_field_type);
+  store_to_memory(ctrl, basic_plus_adr(str, value_offset),
+                  value, T_OBJECT, value_field_idx);
+}
+
+void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
+  int count_offset = java_lang_String::count_offset_in_bytes();
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+  const TypePtr* count_field_type = string_type->add_offset(count_offset);
+  int count_field_idx = C->get_alias_index(count_field_type);
+  store_to_memory(ctrl, basic_plus_adr(str, count_offset),
+                  value, T_INT, count_field_idx);
+}
--- a/src/share/vm/opto/graphKit.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/opto/graphKit.hpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -781,6 +781,14 @@
   Node* new_array(Node* klass_node, Node* count_val, int nargs,
                   Node* *return_size_val = NULL);
 
+  // java.lang.String helpers
+  Node* load_String_offset(Node* ctrl, Node* str);
+  Node* load_String_length(Node* ctrl, Node* str);
+  Node* load_String_value(Node* ctrl, Node* str);
+  void store_String_offset(Node* ctrl, Node* str, Node* value);
+  void store_String_length(Node* ctrl, Node* str, Node* value);
+  void store_String_value(Node* ctrl, Node* str, Node* value);
+
   // Handy for making control flow
   IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
     IfNode* iff = new (C, 2) IfNode(ctrl, tst, prob, cnt);// New IfNode's
--- a/src/share/vm/opto/library_call.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/opto/library_call.cpp	Thu May 24 20:04:07 2012 -0400
@@ -147,7 +147,8 @@
     return generate_method_call(method_id, true, false);
   }
 
-  Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2);
+  Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
+  Node* make_string_method_node(int opcode, Node* str1, Node* str2);
   bool inline_string_compareTo();
   bool inline_string_indexOf();
   Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
@@ -873,48 +874,45 @@
 
 
 //------------------------------make_string_method_node------------------------
-// Helper method for String intrinsic finctions.
-Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
-  const int value_offset  = java_lang_String::value_offset_in_bytes();
-  const int count_offset  = java_lang_String::count_offset_in_bytes();
-  const int offset_offset = java_lang_String::offset_offset_in_bytes();
-
+// Helper method for String intrinsic functions. This version is called
+// with str1 and str2 pointing to String object nodes.
+//
+Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
   Node* no_ctrl = NULL;
 
-  ciInstanceKlass* klass = env()->String_klass();
-  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-
-  const TypeAryPtr* value_type =
-        TypeAryPtr::make(TypePtr::NotNull,
-                         TypeAry::make(TypeInt::CHAR,TypeInt::POS),
-                         ciTypeArrayKlass::make(T_CHAR), true, 0);
-
-  // Get start addr of string and substring
-  Node* str1_valuea  = basic_plus_adr(str1, str1, value_offset);
-  Node* str1_value   = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
-  Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
-  Node* str1_offset  = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
+  // Get start addr of string
+  Node* str1_value   = load_String_value(no_ctrl, str1);
+  Node* str1_offset  = load_String_offset(no_ctrl, str1);
   Node* str1_start   = array_element_address(str1_value, str1_offset, T_CHAR);
 
-  Node* str2_valuea  = basic_plus_adr(str2, str2, value_offset);
-  Node* str2_value   = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
-  Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset);
-  Node* str2_offset  = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
+  // Get length of string 1
+  Node* str1_len  = load_String_length(no_ctrl, str1);
+
+  Node* str2_value   = load_String_value(no_ctrl, str2);
+  Node* str2_offset  = load_String_offset(no_ctrl, str2);
   Node* str2_start   = array_element_address(str2_value, str2_offset, T_CHAR);
 
+  Node* str2_len = NULL;
   Node* result = NULL;
+
   switch (opcode) {
   case Op_StrIndexOf:
+    // Get length of string 2
+    str2_len = load_String_length(no_ctrl, str2);
+
     result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
-                                       str1_start, cnt1, str2_start, cnt2);
+                                 str1_start, str1_len, str2_start, str2_len);
     break;
   case Op_StrComp:
+    // Get length of string 2
+    str2_len = load_String_length(no_ctrl, str2);
+
     result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
-                                    str1_start, cnt1, str2_start, cnt2);
+                                 str1_start, str1_len, str2_start, str2_len);
     break;
   case Op_StrEquals:
     result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
-                                      str1_start, str2_start, cnt1);
+                               str1_start, str2_start, str1_len);
     break;
   default:
     ShouldNotReachHere();
@@ -927,15 +925,42 @@
   return _gvn.transform(result);
 }
 
+// Helper method for String intrinsic functions. This version is called
+// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
+// to Int nodes containing the lenghts of str1 and str2.
+//
+Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
+
+  Node* result = NULL;
+  switch (opcode) {
+  case Op_StrIndexOf:
+    result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
+                                 str1_start, cnt1, str2_start, cnt2);
+    break;
+  case Op_StrComp:
+    result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
+                                 str1_start, cnt1, str2_start, cnt2);
+    break;
+  case Op_StrEquals:
+    result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
+                                 str1_start, str2_start, cnt1);
+    break;
+  default:
+    ShouldNotReachHere();
+    return NULL;
+  }
+
+  // All these intrinsics have checks.
+  C->set_has_split_ifs(true); // Has chance for split-if optimization
+
+  return _gvn.transform(result);
+}
+
 //------------------------------inline_string_compareTo------------------------
 bool LibraryCallKit::inline_string_compareTo() {
 
   if (!Matcher::has_match_rule(Op_StrComp)) return false;
 
-  const int value_offset = java_lang_String::value_offset_in_bytes();
-  const int count_offset = java_lang_String::count_offset_in_bytes();
-  const int offset_offset = java_lang_String::offset_offset_in_bytes();
-
   _sp += 2;
   Node *argument = pop();  // pop non-receiver first:  it was pushed second
   Node *receiver = pop();
@@ -952,18 +977,7 @@
     return true;
   }
 
-  ciInstanceKlass* klass = env()->String_klass();
-  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-  Node* no_ctrl = NULL;
-
-  // Get counts for string and argument
-  Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
-  Node* receiver_cnt  = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
-
-  Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
-  Node* argument_cnt  = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
-
-  Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt);
+  Node* compare = make_string_method_node(Op_StrComp, receiver, argument);
   push(compare);
   return true;
 }
@@ -973,10 +987,6 @@
 
   if (!Matcher::has_match_rule(Op_StrEquals)) return false;
 
-  const int value_offset = java_lang_String::value_offset_in_bytes();
-  const int count_offset = java_lang_String::count_offset_in_bytes();
-  const int offset_offset = java_lang_String::offset_offset_in_bytes();
-
   int nargs = 2;
   _sp += nargs;
   Node* argument = pop();  // pop non-receiver first:  it was pushed second
@@ -1030,24 +1040,31 @@
     }
   }
 
-  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-
-  Node* no_ctrl = NULL;
-  Node* receiver_cnt;
-  Node* argument_cnt;
-
   if (!stopped()) {
+    const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
+
     // Properly cast the argument to String
     argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
     // This path is taken only when argument's type is String:NotNull.
     argument = cast_not_null(argument, false);
 
-    // Get counts for string and argument
-    Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
-    receiver_cnt  = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
-
-    Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
-    argument_cnt  = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+    Node* no_ctrl = NULL;
+
+    // Get start addr of receiver
+    Node* receiver_val    = load_String_value(no_ctrl, receiver);
+    Node* receiver_offset = load_String_offset(no_ctrl, receiver);
+    Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
+
+    // Get length of receiver
+    Node* receiver_cnt  = load_String_length(no_ctrl, receiver);
+
+    // Get start addr of argument
+    Node* argument_val   = load_String_value(no_ctrl, argument);
+    Node* argument_offset = load_String_offset(no_ctrl, argument);
+    Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
+
+    // Get length of argument
+    Node* argument_cnt  = load_String_length(no_ctrl, argument);
 
     // Check for receiver count != argument count
     Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
@@ -1057,14 +1074,14 @@
       phi->init_req(4, intcon(0));
       region->init_req(4, if_ne);
     }
-  }
-
-  // Check for count == 0 is done by mach node StrEquals.
-
-  if (!stopped()) {
-    Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt);
-    phi->init_req(1, equals);
-    region->init_req(1, control());
+
+    // Check for count == 0 is done by assembler code for StrEquals.
+
+    if (!stopped()) {
+      Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
+      phi->init_req(1, equals);
+      region->init_req(1, control());
+    }
   }
 
   // post merge
@@ -1162,20 +1179,9 @@
 
   const int nargs = 2; // number of arguments to push back for uncommon trap in predicate
 
-  const int value_offset  = java_lang_String::value_offset_in_bytes();
-  const int count_offset  = java_lang_String::count_offset_in_bytes();
-  const int offset_offset = java_lang_String::offset_offset_in_bytes();
-
-  ciInstanceKlass* klass = env()->String_klass();
-  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-  const TypeAryPtr*  source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
-
-  Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
-  Node* sourceOffset  = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
-  Node* sourceCounta  = basic_plus_adr(string_object, string_object, count_offset);
-  Node* sourceCount   = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
-  Node* sourcea       = basic_plus_adr(string_object, string_object, value_offset);
-  Node* source        = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
+  Node* source        = load_String_value(no_ctrl, string_object);
+  Node* sourceOffset  = load_String_offset(no_ctrl, string_object);
+  Node* sourceCount   = load_String_length(no_ctrl, string_object);
 
   Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
   jint target_length = target_array->length();
@@ -1243,10 +1249,6 @@
 //------------------------------inline_string_indexOf------------------------
 bool LibraryCallKit::inline_string_indexOf() {
 
-  const int value_offset  = java_lang_String::value_offset_in_bytes();
-  const int count_offset  = java_lang_String::count_offset_in_bytes();
-  const int offset_offset = java_lang_String::offset_offset_in_bytes();
-
   _sp += 2;
   Node *argument = pop();  // pop non-receiver first:  it was pushed second
   Node *receiver = pop();
@@ -1280,12 +1282,21 @@
     Node*       result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT);
     Node* no_ctrl  = NULL;
 
-    // Get counts for string and substr
-    Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);
-    Node* source_cnt  = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
-
-    Node* substr_cnta = basic_plus_adr(argument, argument, count_offset);
-    Node* substr_cnt  = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
+    // Get start addr of source string
+    Node* source = load_String_value(no_ctrl, receiver);
+    Node* source_offset = load_String_offset(no_ctrl, receiver);
+    Node* source_start = array_element_address(source, source_offset, T_CHAR);
+
+    // Get length of source string
+    Node* source_cnt  = load_String_length(no_ctrl, receiver);
+
+    // Get start addr of substring
+    Node* substr = load_String_value(no_ctrl, argument);
+    Node* substr_offset = load_String_offset(no_ctrl, argument);
+    Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
+
+    // Get length of source string
+    Node* substr_cnt  = load_String_length(no_ctrl, argument);
 
     // Check for substr count > string count
     Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
@@ -1308,7 +1319,7 @@
     }
 
     if (!stopped()) {
-      result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt);
+      result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
       result_phi->init_req(1, result);
       result_rgn->init_req(1, control());
     }
@@ -1333,11 +1344,19 @@
     ciInstance* str = str_const->as_instance();
     assert(str != NULL, "must be instance");
 
-    ciObject* v = str->field_value_by_offset(value_offset).as_object();
-    int       o = str->field_value_by_offset(offset_offset).as_int();
-    int       c = str->field_value_by_offset(count_offset).as_int();
+    ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
     ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
 
+    int o;
+    int c;
+    if (java_lang_String::has_offset_field()) {
+      o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
+      c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
+    } else {
+      o = 0;
+      c = pat->length();
+    }
+
     // constant strings have no offset and count == length which
     // simplifies the resulting code somewhat so lets optimize for that.
     if (o != 0 || c != pat->length()) {
--- a/src/share/vm/opto/stringopts.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/opto/stringopts.cpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -528,16 +528,6 @@
   }
 
   // Collect the types needed to talk about the various slices of memory
-  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
-                                                     false, NULL, 0);
-
-  const TypePtr* value_field_type = string_type->add_offset(java_lang_String::value_offset_in_bytes());
-  const TypePtr* offset_field_type = string_type->add_offset(java_lang_String::offset_offset_in_bytes());
-  const TypePtr* count_field_type = string_type->add_offset(java_lang_String::count_offset_in_bytes());
-
-  value_field_idx = C->get_alias_index(value_field_type);
-  count_field_idx = C->get_alias_index(count_field_type);
-  offset_field_idx = C->get_alias_index(offset_field_type);
   char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
 
   // For each locally allocated StringBuffer see if the usages can be
@@ -1174,18 +1164,9 @@
 
 Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
   Node* string = str;
-  Node* offset = kit.make_load(kit.control(),
-                               kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
-                               TypeInt::INT, T_INT, offset_field_idx);
-  Node* count = kit.make_load(kit.control(),
-                              kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
-                              TypeInt::INT, T_INT, count_field_idx);
-  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
-                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
-                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
-  Node* value = kit.make_load(kit.control(),
-                              kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
-                              value_type, T_OBJECT, value_field_idx);
+  Node* offset = kit.load_String_offset(kit.control(), string);
+  Node* count  = kit.load_String_length(kit.control(), string);
+  Node* value  = kit.load_String_value (kit.control(), string);
 
   // copy the contents
   if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) {
@@ -1342,10 +1323,9 @@
           arg = phi;
           sc->set_argument(argi, arg);
         }
-        //         Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
-        //                                      TypeInt::INT, T_INT, offset_field_idx);
-        Node* count = kit.make_load(kit.control(), kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
-                                    TypeInt::INT, T_INT, count_field_idx);
+
+        Node* count = kit.load_String_length(kit.control(), arg);
+
         length = __ AddI(length, count);
         string_sizes->init_req(argi, NULL);
         break;
@@ -1436,12 +1416,11 @@
   }
 
   // Intialize the string
-  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::offset_offset_in_bytes()),
-                      __ intcon(0), T_INT, offset_field_idx);
-  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::count_offset_in_bytes()),
-                      length, T_INT, count_field_idx);
-  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::value_offset_in_bytes()),
-                      char_array, T_OBJECT, value_field_idx);
+  if (java_lang_String::has_offset_field()) {
+    kit.store_String_offset(kit.control(), result, __ intcon(0));
+    kit.store_String_length(kit.control(), result, length);
+  }
+  kit.store_String_value(kit.control(), result, char_array);
 
   // hook up the outgoing control and result
   kit.replace_call(sc->end(), result);
--- a/src/share/vm/opto/stringopts.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/opto/stringopts.hpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,6 @@
 
   // Memory slices needed for code gen
   int char_adr_idx;
-  int value_field_idx;
-  int count_field_idx;
-  int offset_field_idx;
 
   // Integer.sizeTable - used for int to String conversion
   ciField* size_table_field;
--- a/src/share/vm/runtime/arguments.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Thu May 24 20:04:07 2012 -0400
@@ -3039,7 +3039,7 @@
     return result;
   }
 
-#ifdef JAVASE_EMBEDDED
+#if (defined JAVASE_EMBEDDED || defined ARM)
   UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
 #endif
 
@@ -3092,6 +3092,14 @@
     PrintGC = true;
   }
 
+  if (!JDK_Version::is_gte_jdk18x_version()) {
+    // To avoid changing the log format for 7 updates this flag is only
+    // true by default in JDK8 and above.
+    if (FLAG_IS_DEFAULT(PrintGCCause)) {
+      FLAG_SET_DEFAULT(PrintGCCause, false);
+    }
+  }
+
   // Set object alignment values.
   set_object_alignment();
 
--- a/src/share/vm/runtime/globals.cpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/runtime/globals.cpp	Thu May 24 20:04:07 2012 -0400
@@ -148,6 +148,8 @@
     st->print("-XX:%s=" UINTX_FORMAT, name, get_uintx());
   } else if (is_uint64_t()) {
     st->print("-XX:%s=" UINT64_FORMAT, name, get_uint64_t());
+  } else if (is_double()) {
+    st->print("-XX:%s=%f", name, get_double());
   } else if (is_ccstr()) {
     st->print("-XX:%s=", name);
     const char* cp = get_ccstr();
--- a/src/share/vm/runtime/globals.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/runtime/globals.hpp	Thu May 24 20:04:07 2012 -0400
@@ -3902,7 +3902,10 @@
           " of this flag is true for JDK 6 and earlier")                    \
                                                                             \
   diagnostic(bool, WhiteBoxAPI, false,                                      \
-          "Enable internal testing APIs")
+          "Enable internal testing APIs")                                   \
+                                                                            \
+  product(bool, PrintGCCause, true,                                         \
+          "Include GC cause in GC logging")
 
 /*
  *  Macros for factoring of globals
--- a/src/share/vm/runtime/java.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/runtime/java.hpp	Thu May 24 20:04:07 2012 -0400
@@ -206,6 +206,10 @@
     return current().compare_major(7) == 0;
   }
 
+  static bool is_jdk18x_version() {
+    return current().compare_major(8) == 0;
+  }
+
   static bool is_gte_jdk13x_version() {
     return current().compare_major(3) >= 0;
   }
@@ -225,6 +229,10 @@
   static bool is_gte_jdk17x_version() {
     return current().compare_major(7) >= 0;
   }
+
+  static bool is_gte_jdk18x_version() {
+    return current().compare_major(8) >= 0;
+  }
 };
 
 #endif // SHARE_VM_RUNTIME_JAVA_HPP
--- a/src/share/vm/utilities/globalDefinitions.hpp	Thu May 24 13:37:47 2012 +0200
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Thu May 24 20:04:07 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -179,6 +179,11 @@
 const jint  NANOSECS_PER_MILLISEC = 1000000;
 
 inline const char* proper_unit_for_byte_size(size_t s) {
+#ifdef _LP64
+  if (s >= 10*G) {
+    return "G";
+  }
+#endif
   if (s >= 10*M) {
     return "M";
   } else if (s >= 10*K) {
@@ -188,17 +193,22 @@
   }
 }
 
-inline size_t byte_size_in_proper_unit(size_t s) {
+template <class T>
+inline T byte_size_in_proper_unit(T s) {
+#ifdef _LP64
+  if (s >= 10*G) {
+    return (T)(s/G);
+  }
+#endif
   if (s >= 10*M) {
-    return s/M;
+    return (T)(s/M);
   } else if (s >= 10*K) {
-    return s/K;
+    return (T)(s/K);
   } else {
     return s;
   }
 }
 
-
 //----------------------------------------------------------------------------------------------------
 // VM type definitions
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7167069/PrintAsFlag.java	Thu May 24 20:04:07 2012 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * Note that in the run command below the only important flag is PrintCommandLineFlags.
+ * The others are just flags of all types; bool, intx, uintx, uint64_t, double and ccstr.
+ *
+ * @test PrintAsFlag
+ * @summary verify that Flag::print_as_flag() works correctly. This is used by "jinfo -flag" and -XX:+PrintCommandLineFlags.
+ * @run main/othervm -XX:+PrintCommandLineFlags -XX:-ShowMessageBoxOnError -XX:BiasedLockingStartupDelay=4000 -XX:ParallelGCThreads=4 -XX:MaxRAM=1G -XX:CMSSmallCoalSurplusPercent=1.05 -XX:ErrorFile="file" PrintAsFlag
+ */
+
+public class PrintAsFlag {
+  public static void main(String... args) {
+    System.out.printf("Done");
+  }
+}