Merge
authorduke
Wed, 05 Jul 2017 16:50:32 +0200
changeset 2415 b273ee3f0e8e
parent 2414 629fcf301ed8 (current diff)
parent 2413 d9bd989cbc46 (diff)
child 2417 bd1dce471e2a
Merge
jdk/src/windows/classes/sun/awt/windows/fontconfig.98.properties
jdk/src/windows/classes/sun/awt/windows/fontconfig.Me.properties
--- a/.hgtags-top-repo	Thu Apr 02 16:51:48 2009 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 16:50:32 2017 +0200
@@ -27,3 +27,4 @@
 5111e13e44e542fe945b47ab154546daec36737d jdk7-b50
 0f0189d55ce4a1f7840da7582ac7d970b3b7ab15 jdk7-b51
 4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52
+c235f4a8559d196879c56af80159f67ee5d0e720 jdk7-b53
--- a/corba/.hgtags	Thu Apr 02 16:51:48 2009 -0700
+++ b/corba/.hgtags	Wed Jul 05 16:50:32 2017 +0200
@@ -27,3 +27,4 @@
 0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50
 3eb8f1047a7402a9a79937d1c39560e931e91da2 jdk7-b51
 bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52
+3c4d73194f6f89f040ae3b2d257335dfa8a1b2b5 jdk7-b53
--- a/hotspot/.hgtags	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 16:50:32 2017 +0200
@@ -27,3 +27,4 @@
 dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50
 2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51
 1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52
+032c6af894dae8d939b3dd31d82042549e7793e0 jdk7-b53
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java	Wed Jul 05 16:50:32 2017 +0200
@@ -46,12 +46,18 @@
     Type type = db.lookupType("StubRoutines");
 
     callStubReturnAddressField = type.getAddressField("_call_stub_return_address");
-    // Only some platforms have specif return from compiled to call_stub
+    // Only some platforms have specific return from compiled to call_stub
     try {
-      callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return");
+      type = db.lookupType("StubRoutines::x86");
+      if (type != null) {
+        callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return");
+      }
     } catch (RuntimeException re) {
       callStubCompiledReturnAddressField = null;
     }
+    if (callStubCompiledReturnAddressField == null && VM.getVM().getCPU().equals("x86")) {
+      throw new InternalError("Missing definition for _call_stub_compiled_return");
+    }
   }
 
   public StubRoutines() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Wed Jul 05 16:50:32 2017 +0200
@@ -342,8 +342,10 @@
       throw new RuntimeException("Attempt to initialize VM twice");
     }
     soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian());
+
     debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(),
                           Universe.getNarrowOopShift());
+
     for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
       ((Observer) iter.next()).update(null, null);
     }
--- a/hotspot/make/hotspot_version	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/make/hotspot_version	Wed Jul 05 16:50:32 2017 +0200
@@ -31,11 +31,11 @@
 #
 
 # Don't put quotes (fail windows build).
-HOTSPOT_VM_COPYRIGHT=Copyright 2008
+HOTSPOT_VM_COPYRIGHT=Copyright 2009
 
 HS_MAJOR_VER=15
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=04
+HS_BUILD_NUMBER=05
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2615,12 +2615,12 @@
   }
 }
 
-RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
-                                               Register tmp,
-                                               int offset) {
+RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr,
+                                                      Register tmp,
+                                                      int offset) {
   intptr_t value = *delayed_value_addr;
   if (value != 0)
-    return RegisterConstant(value + offset);
+    return RegisterOrConstant(value + offset);
 
   // load indirectly to solve generation ordering problem
   Address a(tmp, (address) delayed_value_addr);
@@ -2634,11 +2634,11 @@
   if (offset != 0)
     add(tmp, offset, tmp);
 
-  return RegisterConstant(tmp);
+  return RegisterOrConstant(tmp);
 }
 
 
-void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
+void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) {
   assert(dest.register_or_noreg() != G0, "lost side effect");
   if ((src.is_constant() && src.as_constant() == 0) ||
       (src.is_register() && src.as_register() == G0)) {
@@ -2647,15 +2647,15 @@
     add(dest.as_register(), ensure_rs2(src, temp), dest.as_register());
   } else if (src.is_constant()) {
     intptr_t res = dest.as_constant() + src.as_constant();
-    dest = RegisterConstant(res); // side effect seen by caller
+    dest = RegisterOrConstant(res); // side effect seen by caller
   } else {
     assert(temp != noreg, "cannot handle constant += register");
     add(src.as_register(), ensure_rs2(dest, temp), temp);
-    dest = RegisterConstant(temp); // side effect seen by caller
+    dest = RegisterOrConstant(temp); // side effect seen by caller
   }
 }
 
-void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
+void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) {
   assert(dest.register_or_noreg() != G0, "lost side effect");
   if (!is_simm13(src.constant_or_zero()))
     src = (src.as_constant() & 0xFF);
@@ -2666,12 +2666,12 @@
     sll_ptr(dest.as_register(), src, dest.as_register());
   } else if (src.is_constant()) {
     intptr_t res = dest.as_constant() << src.as_constant();
-    dest = RegisterConstant(res); // side effect seen by caller
+    dest = RegisterOrConstant(res); // side effect seen by caller
   } else {
     assert(temp != noreg, "cannot handle constant <<= register");
     set(dest.as_constant(), temp);
     sll_ptr(temp, src, temp);
-    dest = RegisterConstant(temp); // side effect seen by caller
+    dest = RegisterOrConstant(temp); // side effect seen by caller
   }
 }
 
@@ -2683,7 +2683,7 @@
 // On failure, execution transfers to the given label.
 void MacroAssembler::lookup_interface_method(Register recv_klass,
                                              Register intf_klass,
-                                             RegisterConstant itable_index,
+                                             RegisterOrConstant itable_index,
                                              Register method_result,
                                              Register scan_temp,
                                              Register sethi_temp,
@@ -2720,7 +2720,7 @@
   add(recv_klass, scan_temp, scan_temp);
 
   // Adjust recv_klass by scaled itable_index, so we can free itable_index.
-  RegisterConstant itable_offset = itable_index;
+  RegisterOrConstant itable_offset = itable_index;
   regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
   regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes());
   add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass);
@@ -2805,7 +2805,7 @@
                                                    Label* L_success,
                                                    Label* L_failure,
                                                    Label* L_slow_path,
-                                        RegisterConstant super_check_offset,
+                                        RegisterOrConstant super_check_offset,
                                         Register instanceof_hack) {
   int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
                    Klass::secondary_super_cache_offset_in_bytes());
@@ -2867,7 +2867,7 @@
   if (must_load_sco) {
     // The super check offset is always positive...
     lduw(super_klass, sco_offset, temp2_reg);
-    super_check_offset = RegisterConstant(temp2_reg);
+    super_check_offset = RegisterOrConstant(temp2_reg);
   }
   ld_ptr(sub_klass, super_check_offset, temp_reg);
   cmp(super_klass, temp_reg);
@@ -4234,7 +4234,6 @@
 static jint num_ct_writes = 0;
 static jint num_ct_writes_filtered_in_hr = 0;
 static jint num_ct_writes_filtered_null = 0;
-static jint num_ct_writes_filtered_pop = 0;
 static G1CollectedHeap* g1 = NULL;
 
 static Thread* count_ct_writes(void* filter_val, void* new_val) {
@@ -4247,25 +4246,19 @@
     if (g1 == NULL) {
       g1 = G1CollectedHeap::heap();
     }
-    if ((HeapWord*)new_val < g1->popular_object_boundary()) {
-      Atomic::inc(&num_ct_writes_filtered_pop);
-    }
   }
   if ((num_ct_writes % 1000000) == 0) {
     jint num_ct_writes_filtered =
       num_ct_writes_filtered_in_hr +
-      num_ct_writes_filtered_null +
-      num_ct_writes_filtered_pop;
+      num_ct_writes_filtered_null;
 
     tty->print_cr("%d potential CT writes: %5.2f%% filtered\n"
-                  "   (%5.2f%% intra-HR, %5.2f%% null, %5.2f%% popular).",
+                  "   (%5.2f%% intra-HR, %5.2f%% null).",
                   num_ct_writes,
                   100.0*(float)num_ct_writes_filtered/(float)num_ct_writes,
                   100.0*(float)num_ct_writes_filtered_in_hr/
                   (float)num_ct_writes,
                   100.0*(float)num_ct_writes_filtered_null/
-                  (float)num_ct_writes,
-                  100.0*(float)num_ct_writes_filtered_pop/
                   (float)num_ct_writes);
   }
   return Thread::current();
@@ -4472,7 +4465,7 @@
 }
 
 // Loading values by size and signed-ness
-void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d,
+void MacroAssembler::load_sized_value(Register s1, RegisterOrConstant s2, Register d,
                                       int size_in_bytes, bool is_signed) {
   switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
   case ~8:  // fall through:
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1088,8 +1088,8 @@
   inline void add(    Register s1, Register s2, Register d );
   inline void add(    Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
   inline void add(    Register s1, int simm13a, Register d, RelocationHolder const& rspec);
-  inline void add(    Register s1, RegisterConstant s2, Register d, int offset = 0);
-  inline void add(    const Address&  a,              Register d, int offset = 0);
+  inline void add(    Register s1, RegisterOrConstant s2, Register d, int offset = 0);
+  inline void add(    const Address&  a,                  Register d, int offset = 0);
 
   void addcc(  Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3  | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
   void addcc(  Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3  | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
@@ -1305,15 +1305,15 @@
   inline void ld(   const Address& a, Register d, int offset = 0 );
   inline void ldd(  const Address& a, Register d, int offset = 0 );
 
-  inline void ldub(  Register s1, RegisterConstant s2, Register d );
-  inline void ldsb(  Register s1, RegisterConstant s2, Register d );
-  inline void lduh(  Register s1, RegisterConstant s2, Register d );
-  inline void ldsh(  Register s1, RegisterConstant s2, Register d );
-  inline void lduw(  Register s1, RegisterConstant s2, Register d );
-  inline void ldsw(  Register s1, RegisterConstant s2, Register d );
-  inline void ldx(   Register s1, RegisterConstant s2, Register d );
-  inline void ld(    Register s1, RegisterConstant s2, Register d );
-  inline void ldd(   Register s1, RegisterConstant s2, Register d );
+  inline void ldub(  Register s1, RegisterOrConstant s2, Register d );
+  inline void ldsb(  Register s1, RegisterOrConstant s2, Register d );
+  inline void lduh(  Register s1, RegisterOrConstant s2, Register d );
+  inline void ldsh(  Register s1, RegisterOrConstant s2, Register d );
+  inline void lduw(  Register s1, RegisterOrConstant s2, Register d );
+  inline void ldsw(  Register s1, RegisterOrConstant s2, Register d );
+  inline void ldx(   Register s1, RegisterOrConstant s2, Register d );
+  inline void ld(    Register s1, RegisterOrConstant s2, Register d );
+  inline void ldd(   Register s1, RegisterOrConstant s2, Register d );
 
   // pp 177
 
@@ -1535,12 +1535,12 @@
   inline void st(   Register d, const Address& a, int offset = 0 );
   inline void std(  Register d, const Address& a, int offset = 0 );
 
-  inline void stb(  Register d, Register s1, RegisterConstant s2 );
-  inline void sth(  Register d, Register s1, RegisterConstant s2 );
-  inline void stw(  Register d, Register s1, RegisterConstant s2 );
-  inline void stx(  Register d, Register s1, RegisterConstant s2 );
-  inline void std(  Register d, Register s1, RegisterConstant s2 );
-  inline void st(   Register d, Register s1, RegisterConstant s2 );
+  inline void stb(  Register d, Register s1, RegisterOrConstant s2 );
+  inline void sth(  Register d, Register s1, RegisterOrConstant s2 );
+  inline void stw(  Register d, Register s1, RegisterOrConstant s2 );
+  inline void stx(  Register d, Register s1, RegisterOrConstant s2 );
+  inline void std(  Register d, Register s1, RegisterOrConstant s2 );
+  inline void st(   Register d, Register s1, RegisterOrConstant s2 );
 
   // pp 177
 
@@ -1859,7 +1859,7 @@
   // Functions for isolating 64 bit shifts for LP64
   inline void sll_ptr( Register s1, Register s2, Register d );
   inline void sll_ptr( Register s1, int imm6a,   Register d );
-  inline void sll_ptr( Register s1, RegisterConstant s2, Register d );
+  inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d );
   inline void srl_ptr( Register s1, Register s2, Register d );
   inline void srl_ptr( Register s1, int imm6a,   Register d );
 
@@ -1965,26 +1965,26 @@
   // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
   inline void ld_ptr(   Register s1, Register s2, Register d );
   inline void ld_ptr(   Register s1, int simm13a, Register d);
-  inline void ld_ptr(   Register s1, RegisterConstant s2, Register d );
+  inline void ld_ptr(   Register s1, RegisterOrConstant s2, Register d );
   inline void ld_ptr(  const Address& a, Register d, int offset = 0 );
   inline void st_ptr(  Register d, Register s1, Register s2 );
   inline void st_ptr(  Register d, Register s1, int simm13a);
-  inline void st_ptr(  Register d, Register s1, RegisterConstant s2 );
+  inline void st_ptr(  Register d, Register s1, RegisterOrConstant s2 );
   inline void st_ptr(  Register d, const Address& a, int offset = 0 );
 
   // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
   // st_long will perform st for 32 bit VM's and stx for 64 bit VM's
   inline void ld_long( Register s1, Register s2, Register d );
   inline void ld_long( Register s1, int simm13a, Register d );
-  inline void ld_long( Register s1, RegisterConstant s2, Register d );
+  inline void ld_long( Register s1, RegisterOrConstant s2, Register d );
   inline void ld_long( const Address& a, Register d, int offset = 0 );
   inline void st_long( Register d, Register s1, Register s2 );
   inline void st_long( Register d, Register s1, int simm13a );
-  inline void st_long( Register d, Register s1, RegisterConstant s2 );
+  inline void st_long( Register d, Register s1, RegisterOrConstant s2 );
   inline void st_long( Register d, const Address& a, int offset = 0 );
 
   // Loading values by size and signed-ness
-  void load_sized_value(Register s1, RegisterConstant s2, Register d,
+  void load_sized_value(Register s1, RegisterOrConstant s2, Register d,
                         int size_in_bytes, bool is_signed);
 
   // Helpers for address formation.
@@ -1994,11 +1994,11 @@
   // is required, and becomes the result.
   // If dest is a register and src is a non-simm13 constant,
   // the temp argument is required, and is used to materialize the constant.
-  void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src,
+  void regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src,
                        Register temp = noreg );
-  void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src,
+  void regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src,
                        Register temp = noreg );
-  RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) {
+  RegisterOrConstant ensure_rs2(RegisterOrConstant rs2, Register sethi_temp) {
     guarantee(sethi_temp != noreg, "constant offset overflow");
     if (is_simm13(rs2.constant_or_zero()))
       return rs2;               // register or short constant
@@ -2322,7 +2322,7 @@
   // interface method calling
   void lookup_interface_method(Register recv_klass,
                                Register intf_klass,
-                               RegisterConstant itable_index,
+                               RegisterOrConstant itable_index,
                                Register method_result,
                                Register temp_reg, Register temp2_reg,
                                Label& no_such_interface);
@@ -2341,7 +2341,7 @@
                                      Label* L_success,
                                      Label* L_failure,
                                      Label* L_slow_path,
-                RegisterConstant super_check_offset = RegisterConstant(-1),
+                RegisterOrConstant super_check_offset = RegisterOrConstant(-1),
                 Register instanceof_hack = noreg);
 
   // The rest of the type check; must be wired to a corresponding fast path.
@@ -2381,7 +2381,7 @@
   // stack overflow + shadow pages.  Clobbers tsp and scratch registers.
   void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
 
-  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset);
+  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset);
 
   void verify_tlab();
 
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,45 +143,45 @@
 inline void Assembler::ld(  Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
 #endif
 
-inline void Assembler::ldub(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldub(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsb(s1, s2.as_register(), d);
   else                   ldsb(s1, s2.as_constant(), d);
 }
-inline void Assembler::ldsb(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldsb(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsb(s1, s2.as_register(), d);
   else                   ldsb(s1, s2.as_constant(), d);
 }
-inline void Assembler::lduh(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::lduh(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsh(s1, s2.as_register(), d);
   else                   ldsh(s1, s2.as_constant(), d);
 }
-inline void Assembler::ldsh(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldsh(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsh(s1, s2.as_register(), d);
   else                   ldsh(s1, s2.as_constant(), d);
 }
-inline void Assembler::lduw(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::lduw(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsw(s1, s2.as_register(), d);
   else                   ldsw(s1, s2.as_constant(), d);
 }
-inline void Assembler::ldsw(  Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldsw(  Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldsw(s1, s2.as_register(), d);
   else                   ldsw(s1, s2.as_constant(), d);
 }
-inline void Assembler::ldx(   Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldx(   Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldx(s1, s2.as_register(), d);
   else                   ldx(s1, s2.as_constant(), d);
 }
-inline void Assembler::ld(    Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ld(    Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ld(s1, s2.as_register(), d);
   else                   ld(s1, s2.as_constant(), d);
 }
-inline void Assembler::ldd(   Register s1, RegisterConstant s2, Register d) {
+inline void Assembler::ldd(   Register s1, RegisterOrConstant s2, Register d) {
   if (s2.is_register())  ldd(s1, s2.as_register(), d);
   else                   ldd(s1, s2.as_constant(), d);
 }
 
 // form effective addresses this way:
-inline void Assembler::add(   Register s1, RegisterConstant s2, Register d, int offset) {
+inline void Assembler::add(   Register s1, RegisterOrConstant s2, Register d, int offset) {
   if (s2.is_register())  add(s1, s2.as_register(), d);
   else                 { add(s1, s2.as_constant() + offset, d); offset = 0; }
   if (offset != 0)       add(d,  offset,                    d);
@@ -243,23 +243,23 @@
 inline void Assembler::st(  Register d, Register s1, Register s2) { stw(d, s1, s2); }
 inline void Assembler::st(  Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
 
-inline void Assembler::stb(  Register d, Register s1, RegisterConstant s2) {
+inline void Assembler::stb(  Register d, Register s1, RegisterOrConstant s2) {
   if (s2.is_register())  stb(d, s1, s2.as_register());
   else                   stb(d, s1, s2.as_constant());
 }
-inline void Assembler::sth(  Register d, Register s1, RegisterConstant s2) {
+inline void Assembler::sth(  Register d, Register s1, RegisterOrConstant s2) {
   if (s2.is_register())  sth(d, s1, s2.as_register());
   else                   sth(d, s1, s2.as_constant());
 }
-inline void Assembler::stx(  Register d, Register s1, RegisterConstant s2) {
+inline void Assembler::stx(  Register d, Register s1, RegisterOrConstant s2) {
   if (s2.is_register())  stx(d, s1, s2.as_register());
   else                   stx(d, s1, s2.as_constant());
 }
-inline void Assembler::std( Register d, Register s1, RegisterConstant s2) {
+inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) {
   if (s2.is_register())  std(d, s1, s2.as_register());
   else                   std(d, s1, s2.as_constant());
 }
-inline void Assembler::st(  Register d, Register s1, RegisterConstant s2) {
+inline void Assembler::st(  Register d, Register s1, RegisterOrConstant s2) {
   if (s2.is_register())  st(d, s1, s2.as_register());
   else                   st(d, s1, s2.as_constant());
 }
@@ -308,7 +308,7 @@
 #endif
 }
 
-inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) {
+inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) {
 #ifdef _LP64
   Assembler::ldx( s1, s2, d);
 #else
@@ -340,7 +340,7 @@
 #endif
 }
 
-inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) {
+inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) {
 #ifdef _LP64
   Assembler::stx( d, s1, s2);
 #else
@@ -373,7 +373,7 @@
 #endif
 }
 
-inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) {
+inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) {
 #ifdef _LP64
   Assembler::ldx(s1, s2, d);
 #else
@@ -405,7 +405,7 @@
 #endif
 }
 
-inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) {
+inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) {
 #ifdef _LP64
   Assembler::stx(d, s1, s2);
 #else
@@ -455,7 +455,7 @@
 #endif
 }
 
-inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) {
+inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) {
   if (s2.is_register())  sll_ptr(s1, s2.as_register(), d);
   else                   sll_ptr(s1, s2.as_constant(), d);
 }
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2489,7 +2489,7 @@
         __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg,
                                          (need_slow_path ? &done : NULL),
                                          stub->entry(), NULL,
-                                         RegisterConstant(k->super_check_offset()));
+                                         RegisterOrConstant(k->super_check_offset()));
       } else {
         // perform the fast part of the checking logic
         __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7,
@@ -2550,14 +2550,14 @@
         __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg,
                                          (need_slow_path ? &done : NULL),
                                          (need_slow_path ? &done : NULL), NULL,
-                                         RegisterConstant(k->super_check_offset()),
+                                         RegisterOrConstant(k->super_check_offset()),
                                          dst);
       } else {
         assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers");
         // perform the fast part of the checking logic
         __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst,
                                          &done, &done, NULL,
-                                         RegisterConstant(-1),
+                                         RegisterOrConstant(-1),
                                          dst);
       }
       if (need_slow_path) {
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -46,6 +46,7 @@
 define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K))));
 define_pd_global(intx,  SurvivorRatio,         8);
 define_pd_global(intx,  InlineFrequencyCount,  50);  // we can use more inlining on the SPARC
+define_pd_global(intx,  InlineSmallCode,       1500);
 #ifdef _LP64
 // Stack slots are 2X larger in LP64 than in the 32 bit VM.
 define_pd_global(intx,  ThreadStackSize,       1024);
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 16:50:32 2017 +0200
@@ -3003,6 +3003,202 @@
     __ bind(Ldone);
   %}
 
+enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
+    Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
+    MacroAssembler _masm(&cbuf);
+
+    Register   str1_reg = reg_to_register_object($str1$$reg);
+    Register   str2_reg = reg_to_register_object($str2$$reg);
+    Register   tmp1_reg = reg_to_register_object($tmp1$$reg);
+    Register   tmp2_reg = reg_to_register_object($tmp2$$reg);
+    Register result_reg = reg_to_register_object($result$$reg);
+
+    // Get the first character position in both strings
+    //         [8] char array, [12] offset, [16] count
+    int  value_offset = java_lang_String:: value_offset_in_bytes();
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    int  count_offset = java_lang_String:: count_offset_in_bytes();
+
+    // load str1 (jchar*) base address into tmp1_reg
+    __ load_heap_oop(Address(str1_reg, 0,  value_offset), tmp1_reg);
+    __ ld(Address(str1_reg, 0, offset_offset), result_reg);
+    __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
+    __    ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted
+    __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
+    __    load_heap_oop(Address(str2_reg, 0,  value_offset), tmp2_reg); // hoisted
+    __ add(result_reg, tmp1_reg, tmp1_reg);
+
+    // load str2 (jchar*) base address into tmp2_reg
+    // __ ld_ptr(Address(str2_reg, 0,  value_offset), tmp2_reg); // hoisted
+    __ ld(Address(str2_reg, 0, offset_offset), result_reg);
+    __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
+    __    ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted
+    __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
+    __   cmp(str1_reg, str2_reg); // hoisted
+    __ add(result_reg, tmp2_reg, tmp2_reg);
+
+    __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg);
+    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg);    // not equal
+
+    __ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone);
+    __ delayed()->add(G0, 1, result_reg); //equals
+
+    __ cmp(tmp1_reg, tmp2_reg); //same string ?
+    __ brx(Assembler::equal, true, Assembler::pn, Ldone);
+    __ delayed()->add(G0, 1, result_reg);
+
+    //rename registers
+    Register limit_reg =   str1_reg;
+    Register  chr2_reg =   str2_reg;
+    Register  chr1_reg = result_reg;
+    // tmp{12} are the base pointers
+
+    //check for alignment and position the pointers to the ends
+    __ or3(tmp1_reg, tmp2_reg, chr1_reg);
+    __ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned
+    __ br(Assembler::notZero, false, Assembler::pn, Lchar);
+    __ delayed()->nop();
+
+    __ bind(Lword);
+    __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2)
+    __ andn(limit_reg, 0x3, limit_reg);
+    __ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word);
+    __ delayed()->nop();
+
+    __ add(tmp1_reg, limit_reg, tmp1_reg);
+    __ add(tmp2_reg, limit_reg, tmp2_reg);
+    __ neg(limit_reg);
+
+    __ lduw(tmp1_reg, limit_reg, chr1_reg);
+    __ bind(Lword_loop);
+    __ lduw(tmp2_reg, limit_reg, chr2_reg);
+    __ cmp(chr1_reg, chr2_reg);
+    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg);
+    __ inccc(limit_reg, 2*sizeof(jchar));
+    // annul LDUW if branch i  s not taken to prevent access past end of string
+    __ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken
+    __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted
+
+    __ bind(Lpost_word);
+    __ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone);
+    __ delayed()->add(G0, 1, result_reg);
+
+    __ lduh(tmp1_reg, 0, chr1_reg);
+    __ lduh(tmp2_reg, 0, chr2_reg);
+    __ cmp (chr1_reg, chr2_reg);
+    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg);
+    __ ba(false,Ldone);
+    __ delayed()->add(G0, 1, result_reg);
+
+    __ bind(Lchar);
+    __ add(tmp1_reg, limit_reg, tmp1_reg);
+    __ add(tmp2_reg, limit_reg, tmp2_reg);
+    __ neg(limit_reg); //negate count
+
+    __ lduh(tmp1_reg, limit_reg, chr1_reg);
+    __ bind(Lchar_loop);
+    __ lduh(tmp2_reg, limit_reg, chr2_reg);
+    __ cmp(chr1_reg, chr2_reg);
+    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg); //not equal
+    __ inccc(limit_reg, sizeof(jchar));
+    // annul LDUH if branch is not taken to prevent access past end of string
+    __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken
+    __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
+
+    __ add(G0, 1, result_reg);  //equal
+
+    __ bind(Ldone);
+  %}
+
+enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
+    Label Lvector, Ldone, Lloop;
+    MacroAssembler _masm(&cbuf);
+
+    Register   ary1_reg = reg_to_register_object($ary1$$reg);
+    Register   ary2_reg = reg_to_register_object($ary2$$reg);
+    Register   tmp1_reg = reg_to_register_object($tmp1$$reg);
+    Register   tmp2_reg = reg_to_register_object($tmp2$$reg);
+    Register result_reg = reg_to_register_object($result$$reg);
+
+    int length_offset  = arrayOopDesc::length_offset_in_bytes();
+    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // return true if the same array
+    __ cmp(ary1_reg, ary2_reg);
+    __ br(Assembler::equal, true, Assembler::pn, Ldone);
+    __ delayed()->add(G0, 1, result_reg); // equal
+
+    __ br_null(ary1_reg, true, Assembler::pn, Ldone);
+    __ delayed()->mov(G0, result_reg);    // not equal
+
+    __ br_null(ary2_reg, true, Assembler::pn, Ldone);
+    __ delayed()->mov(G0, result_reg);    // not equal
+
+    //load the lengths of arrays
+    __ ld(Address(ary1_reg, 0, length_offset), tmp1_reg);
+    __ ld(Address(ary2_reg, 0, length_offset), tmp2_reg);
+
+    // return false if the two arrays are not equal length
+    __ cmp(tmp1_reg, tmp2_reg);
+    __ br(Assembler::notEqual, true, Assembler::pn, Ldone);
+    __ delayed()->mov(G0, result_reg);     // not equal
+
+    __ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone);
+    __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
+
+    // load array addresses
+    __ add(ary1_reg, base_offset, ary1_reg);
+    __ add(ary2_reg, base_offset, ary2_reg);
+
+    // renaming registers
+    Register chr1_reg  =  tmp2_reg;   // for characters in ary1
+    Register chr2_reg  =  result_reg; // for characters in ary2
+    Register limit_reg =  tmp1_reg;   // length
+
+    // set byte count
+    __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
+    __ andcc(limit_reg, 0x2, chr1_reg); //trailing character ?
+    __ br(Assembler::zero, false, Assembler::pt, Lvector);
+    __ delayed()->nop();
+
+    //compare the trailing char
+    __ sub(limit_reg, sizeof(jchar), limit_reg);
+    __ lduh(ary1_reg, limit_reg, chr1_reg);
+    __ lduh(ary2_reg, limit_reg, chr2_reg);
+    __ cmp(chr1_reg, chr2_reg);
+    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg);     // not equal
+
+    // only one char ?
+    __ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone);
+    __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
+
+    __ bind(Lvector);
+    // Shift ary1_reg and ary2_reg to the end of the arrays, negate limit
+    __ add(ary1_reg, limit_reg, ary1_reg);
+    __ add(ary2_reg, limit_reg, ary2_reg);
+    __ neg(limit_reg, limit_reg);
+
+    __ lduw(ary1_reg, limit_reg, chr1_reg);
+    __ bind(Lloop);
+    __ lduw(ary2_reg, limit_reg, chr2_reg);
+    __ cmp(chr1_reg, chr2_reg);
+    __ br(Assembler::notEqual, false, Assembler::pt, Ldone);
+    __ delayed()->mov(G0, result_reg);     // not equal
+    __ inccc(limit_reg, 2*sizeof(jchar));
+    // annul LDUW if branch is not taken to prevent access past end of string
+    __ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken
+    __ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted
+
+    __ add(G0, 1, result_reg); // equals
+
+    __ bind(Ldone);
+  %}
+
   enc_class enc_rethrow() %{
     cbuf.set_inst_mark();
     Register temp_reg = G3;
@@ -9015,6 +9211,25 @@
   ins_pipe(long_memory_op);
 %}
 
+instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
+                       o7RegI tmp3, flagsReg ccr) %{
+  match(Set result (StrEquals str1 str2));
+  effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
+  ins_cost(300);
+  format %{ "String Equals $str1,$str2 -> $result" %}
+  ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) );
+  ins_pipe(long_memory_op);
+%}
+
+instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
+                        flagsReg ccr) %{
+  match(Set result (AryEq ary1 ary2));
+  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
+  ins_cost(300);
+  format %{ "Array Equals $ary1,$ary2 -> $result" %}
+  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result));
+  ins_pipe(long_memory_op);
+%}
 
 //---------- Population Count Instructions -------------------------------------
 
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -817,21 +817,6 @@
   Label _atomic_add_stub;  // called from other stubs
 
 
-  // Support for void OrderAccess::fence().
-  //
-  address generate_fence() {
-    StubCodeMark mark(this, "StubRoutines", "fence");
-    address start = __ pc();
-
-    __ membar(Assembler::Membar_mask_bits(Assembler::LoadLoad  | Assembler::LoadStore |
-                                          Assembler::StoreLoad | Assembler::StoreStore));
-    __ retl(false);
-    __ delayed()->nop();
-
-    return start;
-  }
-
-
   //------------------------------------------------------------------------------------------------------------------------
   // The following routine generates a subroutine to throw an asynchronous
   // UnknownError when an unsafe access gets a fault that could not be
@@ -2861,7 +2846,6 @@
     StubRoutines::_atomic_cmpxchg_ptr_entry  = StubRoutines::_atomic_cmpxchg_entry;
     StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long();
     StubRoutines::_atomic_add_ptr_entry      = StubRoutines::_atomic_add_entry;
-    StubRoutines::_fence_entry               = generate_fence();
 #endif  // COMPILER2 !=> _LP64
   }
 
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -62,7 +62,7 @@
   if (is_niagara1()) {
     // Indirect branch is the same cost as direct
     if (FLAG_IS_DEFAULT(UseInlineCaches)) {
-      UseInlineCaches         = false;
+      FLAG_SET_DEFAULT(UseInlineCaches, false);
     }
 #ifdef _LP64
     // Single issue niagara1 is slower for CompressedOops
@@ -79,15 +79,19 @@
 #ifdef COMPILER2
     // Indirect branch is the same cost as direct
     if (FLAG_IS_DEFAULT(UseJumpTables)) {
-      UseJumpTables           = true;
+      FLAG_SET_DEFAULT(UseJumpTables, true);
     }
     // Single-issue, so entry and loop tops are
     // aligned on a single instruction boundary
     if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
-      InteriorEntryAlignment  = 4;
+      FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
     }
     if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
-      OptoLoopAlignment       = 4;
+      FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
+    }
+    if (is_niagara1_plus() && FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
+      // Use smaller prefetch distance on N2
+      FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
     }
 #endif
   }
@@ -95,7 +99,7 @@
   // Use hardware population count instruction if available.
   if (has_hardware_popc()) {
     if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
-      UsePopCountInstruction = true;
+      FLAG_SET_DEFAULT(UsePopCountInstruction, true);
     }
   }
 
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1438,26 +1438,12 @@
   }
 }
 
-// Serializes memory.
+// Emit mfence instruction
 void Assembler::mfence() {
-    // Memory barriers are only needed on multiprocessors
-  if (os::is_MP()) {
-    if( LP64_ONLY(true ||) VM_Version::supports_sse2() ) {
-      emit_byte( 0x0F );                // MFENCE; faster blows no regs
-      emit_byte( 0xAE );
-      emit_byte( 0xF0 );
-    } else {
-      // All usable chips support "locked" instructions which suffice
-      // as barriers, and are much faster than the alternative of
-      // using cpuid instruction. We use here a locked add [esp],0.
-      // This is conveniently otherwise a no-op except for blowing
-      // flags (which we save and restore.)
-      pushf();                // Save eflags register
-      lock();
-      addl(Address(rsp, 0), 0);// Assert the lock# signal here
-      popf();                 // Restore eflags register
-    }
-  }
+  NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");)
+  emit_byte( 0x0F );
+  emit_byte( 0xAE );
+  emit_byte( 0xF0 );
 }
 
 void Assembler::mov(Register dst, Register src) {
@@ -2187,6 +2173,31 @@
   emit_arith(0x0B, 0xC0, dst, src);
 }
 
+void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
+  assert(VM_Version::supports_sse4_2(), "");
+
+  InstructionMark im(this);
+  emit_byte(0x66);
+  prefix(src, dst);
+  emit_byte(0x0F);
+  emit_byte(0x3A);
+  emit_byte(0x61);
+  emit_operand(dst, src);
+  emit_byte(imm8);
+}
+
+void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) {
+  assert(VM_Version::supports_sse4_2(), "");
+
+  emit_byte(0x66);
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0x3A);
+  emit_byte(0x61);
+  emit_byte(0xC0 | encode);
+  emit_byte(imm8);
+}
+
 // generic
 void Assembler::pop(Register dst) {
   int encode = prefix_and_encode(dst->encoding());
@@ -2344,6 +2355,29 @@
   emit_byte(shift);
 }
 
+void Assembler::ptest(XMMRegister dst, Address src) {
+  assert(VM_Version::supports_sse4_1(), "");
+
+  InstructionMark im(this);
+  emit_byte(0x66);
+  prefix(src, dst);
+  emit_byte(0x0F);
+  emit_byte(0x38);
+  emit_byte(0x17);
+  emit_operand(dst, src);
+}
+
+void Assembler::ptest(XMMRegister dst, XMMRegister src) {
+  assert(VM_Version::supports_sse4_1(), "");
+
+  emit_byte(0x66);
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0x38);
+  emit_byte(0x17);
+  emit_byte(0xC0 | encode);
+}
+
 void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) {
   NOT_LP64(assert(VM_Version::supports_sse2(), ""));
   emit_byte(0x66);
@@ -7218,7 +7252,7 @@
 // On failure, execution transfers to the given label.
 void MacroAssembler::lookup_interface_method(Register recv_klass,
                                              Register intf_klass,
-                                             RegisterConstant itable_index,
+                                             RegisterOrConstant itable_index,
                                              Register method_result,
                                              Register scan_temp,
                                              Label& L_no_such_interface) {
@@ -7303,7 +7337,7 @@
                                                    Label* L_success,
                                                    Label* L_failure,
                                                    Label* L_slow_path,
-                                        RegisterConstant super_check_offset) {
+                                        RegisterOrConstant super_check_offset) {
   assert_different_registers(sub_klass, super_klass, temp_reg);
   bool must_load_sco = (super_check_offset.constant_or_zero() == -1);
   if (super_check_offset.is_register()) {
@@ -7352,7 +7386,7 @@
   if (must_load_sco) {
     // Positive movl does right thing on LP64.
     movl(temp_reg, super_check_offset_addr);
-    super_check_offset = RegisterConstant(temp_reg);
+    super_check_offset = RegisterOrConstant(temp_reg);
   }
   Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0);
   cmpptr(super_klass, super_check_addr); // load displayed supertype
@@ -7550,12 +7584,12 @@
 }
 
 
-RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
-                                               Register tmp,
-                                               int offset) {
+RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr,
+                                                      Register tmp,
+                                                      int offset) {
   intptr_t value = *delayed_value_addr;
   if (value != 0)
-    return RegisterConstant(value + offset);
+    return RegisterOrConstant(value + offset);
 
   // load indirectly to solve generation ordering problem
   movptr(tmp, ExternalAddress((address) delayed_value_addr));
@@ -7571,7 +7605,7 @@
   if (offset != 0)
     addptr(tmp, offset);
 
-  return RegisterConstant(tmp);
+  return RegisterOrConstant(tmp);
 }
 
 
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -212,7 +212,7 @@
            "inconsistent address");
   }
 
-  Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0)
+  Address(Register base, RegisterOrConstant index, ScaleFactor scale = times_1, int disp = 0)
     : _base (base),
       _index(index.register_or_noreg()),
       _scale(scale),
@@ -256,7 +256,7 @@
            "inconsistent address");
   }
 
-  Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp)
+  Address(Register base, RegisterOrConstant index, ScaleFactor scale, ByteSize disp)
     : _base (base),
       _index(index.register_or_noreg()),
       _scale(scale),
@@ -1068,15 +1068,23 @@
     LoadLoad   = 1 << 0
   };
 
-  // Serializes memory.
+  // Serializes memory and blows flags
   void membar(Membar_mask_bits order_constraint) {
-    // We only have to handle StoreLoad and LoadLoad
-    if (order_constraint & StoreLoad) {
-      // MFENCE subsumes LFENCE
-      mfence();
-    } /* [jk] not needed currently: else if (order_constraint & LoadLoad) {
-         lfence();
-    } */
+    if (os::is_MP()) {
+      // We only have to handle StoreLoad
+      if (order_constraint & StoreLoad) {
+        // All usable chips support "locked" instructions which suffice
+        // as barriers, and are much faster than the alternative of
+        // using cpuid instruction. We use here a locked add [esp],0.
+        // This is conveniently otherwise a no-op except for blowing
+        // flags.
+        // Any change to this code may need to revisit other places in
+        // the code where this idiom is used, in particular the
+        // orderAccess code.
+        lock();
+        addl(Address(rsp, 0), 0);// Assert the lock# signal here
+      }
+    }
   }
 
   void mfence();
@@ -1218,6 +1226,10 @@
   void orq(Register dst, Address src);
   void orq(Register dst, Register src);
 
+  // SSE4.2 string instructions
+  void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
+  void pcmpestri(XMMRegister xmm1, Address src, int imm8);
+
   void popl(Address dst);
 
 #ifdef _LP64
@@ -1252,6 +1264,10 @@
   // Shift Right Logical Quadword Immediate
   void psrlq(XMMRegister dst, int shift);
 
+  // Logical Compare Double Quadword
+  void ptest(XMMRegister dst, XMMRegister src);
+  void ptest(XMMRegister dst, Address src);
+
   // Interleave Low Bytes
   void punpcklbw(XMMRegister dst, XMMRegister src);
 
@@ -1802,7 +1818,7 @@
   // interface method calling
   void lookup_interface_method(Register recv_klass,
                                Register intf_klass,
-                               RegisterConstant itable_index,
+                               RegisterOrConstant itable_index,
                                Register method_result,
                                Register scan_temp,
                                Label& no_such_interface);
@@ -1819,7 +1835,7 @@
                                      Label* L_success,
                                      Label* L_failure,
                                      Label* L_slow_path,
-                RegisterConstant super_check_offset = RegisterConstant(-1));
+                RegisterOrConstant super_check_offset = RegisterOrConstant(-1));
 
   // The rest of the type check; must be wired to a corresponding fast path.
   // It does not repeat the fast path logic, so don't use it standalone.
@@ -1883,9 +1899,9 @@
   // stack overflow + shadow pages.  Also, clobbers tmp
   void bang_stack_size(Register size, Register tmp);
 
-  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr,
-                                         Register tmp,
-                                         int offset);
+  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
+                                                Register tmp,
+                                                int offset);
 
   // Support for serializing memory accesses between threads
   void serialize_memory(Register thread, Register tmp);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -60,6 +60,7 @@
 define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
 #endif // AMD64
 define_pd_global(intx,  InlineFrequencyCount,     100);
+define_pd_global(intx,  InlineSmallCode,          1000);
 define_pd_global(intx,  PreInflateSpin,           10);
 
 define_pd_global(intx, StackYellowPages, 2);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -2691,7 +2691,7 @@
   __ mov(rdi, rax);
 
    Label noException;
-  __ cmpl(r12, Deoptimization::Unpack_exception);   // Was exception pending?
+  __ cmpl(r14, Deoptimization::Unpack_exception);   // Was exception pending?
   __ jcc(Assembler::notEqual, noException);
   __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset()));
   // QQQ this is useless it was NULL above
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -637,7 +637,7 @@
   address generate_orderaccess_fence() {
     StubCodeMark mark(this, "StubRoutines", "orderaccess_fence");
     address start = __ pc();
-    __ mfence();
+    __ membar(Assembler::StoreLoad);
     __ ret(0);
 
     return start;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -408,6 +408,11 @@
           UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
         }
       }
+      if( supports_sse4_2() && UseSSE >= 4 ) {
+        if( FLAG_IS_DEFAULT(UseSSE42Intrinsics)) {
+          UseSSE42Intrinsics = true;
+        }
+      }
     }
   }
 
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 16:50:32 2017 +0200
@@ -3694,12 +3694,16 @@
     }
   %}
 
-  enc_class enc_String_Compare() %{
+  enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
+                        eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{
     Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL,
           POP_LABEL, DONE_LABEL, CONT_LABEL,
           WHILE_HEAD_LABEL;
     MacroAssembler masm(&cbuf);
 
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+
     // Get the first character position in both strings
     //         [8] char array, [12] offset, [16] count
     int value_offset  = java_lang_String::value_offset_in_bytes();
@@ -3717,7 +3721,6 @@
     // Compute the minimum of the string lengths(rsi) and the
     // difference of the string lengths (stack)
 
-
     if (VM_Version::supports_cmov()) {
       masm.movl(rdi, Address(rdi, count_offset));
       masm.movl(rsi, Address(rsi, count_offset));
@@ -3731,7 +3734,7 @@
       masm.movl(rsi, rdi);
       masm.subl(rdi, rcx);
       masm.push(rdi);
-      masm.jcc(Assembler::lessEqual, ECX_GOOD_LABEL);
+      masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL);
       masm.movl(rsi, rcx);
       // rsi holds min, rcx is unused
     }
@@ -3756,7 +3759,7 @@
       Label LSkip2;
       // Check if the strings start at same location
       masm.cmpptr(rbx,rax);
-      masm.jcc(Assembler::notEqual, LSkip2);
+      masm.jccb(Assembler::notEqual, LSkip2);
 
       // Check if the length difference is zero (from stack)
       masm.cmpl(Address(rsp, 0), 0x0);
@@ -3766,9 +3769,52 @@
       masm.bind(LSkip2);
     }
 
-    // Shift rax, and rbx, to the end of the arrays, negate min
-    masm.lea(rax, Address(rax, rsi, Address::times_2, 2));
-    masm.lea(rbx, Address(rbx, rsi, Address::times_2, 2));
+   // Advance to next character
+    masm.addptr(rax, 2);
+    masm.addptr(rbx, 2);
+
+    if (UseSSE42Intrinsics) {
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
+      // Setup to compare 16-byte vectors
+      masm.movl(rdi, rsi);
+      masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
+      masm.andl(rdi, 0x00000007); // rdi holds the tail count
+      masm.testl(rsi, rsi);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+
+      masm.lea(rax, Address(rax, rsi, Address::times_2));
+      masm.lea(rbx, Address(rbx, rsi, Address::times_2));
+      masm.negl(rsi);
+
+      masm.bind(COMPARE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
+      masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+      masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
+      masm.addl(rsi, 8);
+      masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+      masm.jmpb(COMPARE_TAIL);
+
+      // Mismatched characters in the vectors
+      masm.bind(VECTOR_NOT_EQUAL);
+      masm.lea(rax, Address(rax, rsi, Address::times_2));
+      masm.lea(rbx, Address(rbx, rsi, Address::times_2));
+      masm.movl(rdi, 8);
+
+      // Compare tail (< 8 chars), or rescan last vectors to
+      // find 1st mismatched characters
+      masm.bind(COMPARE_TAIL);
+      masm.testl(rdi, rdi);
+      masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
+      masm.movl(rsi, rdi);
+      // Fallthru to tail compare
+    }
+
+    //Shift rax, and rbx, to the end of the arrays, negate min
+    masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
+    masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
     masm.negl(rsi);
 
     // Compare the rest of the characters
@@ -3776,93 +3822,329 @@
     masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
     masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
     masm.subl(rcx, rdi);
-    masm.jcc(Assembler::notZero, POP_LABEL);
+    masm.jccb(Assembler::notZero, POP_LABEL);
     masm.incrementl(rsi);
     masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
 
     // Strings are equal up to min length.  Return the length difference.
     masm.bind(LENGTH_DIFF_LABEL);
     masm.pop(rcx);
-    masm.jmp(DONE_LABEL);
+    masm.jmpb(DONE_LABEL);
 
     // Discard the stored length difference
     masm.bind(POP_LABEL);
     masm.addptr(rsp, 4);
-       
+
     // That's it
     masm.bind(DONE_LABEL);
   %}
 
-  enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result) %{
-    Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP;
+ enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
+                       eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{
+    Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
+    MacroAssembler masm(&cbuf);
+
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+
+    int value_offset  = java_lang_String::value_offset_in_bytes();
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    int count_offset  = java_lang_String::count_offset_in_bytes();
+    int base_offset   = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // does source == target string?
+    masm.cmpptr(rdi, rsi);
+    masm.jcc(Assembler::equal, RET_TRUE);
+
+    // get and compare counts
+    masm.movl(rcx, Address(rdi, count_offset));
+    masm.movl(rax, Address(rsi, count_offset));
+    masm.cmpl(rcx, rax);
+    masm.jcc(Assembler::notEqual, RET_FALSE);
+    masm.testl(rax, rax);
+    masm.jcc(Assembler::zero, RET_TRUE);
+
+    // get source string offset and value
+    masm.movptr(rbx, Address(rsi, value_offset));
+    masm.movl(rax, Address(rsi, offset_offset));
+    masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset));
+
+    // get compare string offset and value
+    masm.movptr(rbx, Address(rdi, value_offset));
+    masm.movl(rax, Address(rdi, offset_offset));
+    masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset));
+
+    // Set byte count
+    masm.shll(rcx, 1);
+    masm.movl(rax, rcx);
+
+    if (UseSSE42Intrinsics) {
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+      // Compare 16-byte vectors
+      masm.andl(rcx, 0xfffffff0);  // vector count (in bytes)
+      masm.andl(rax, 0x0000000e);  // tail count (in bytes)
+      masm.testl(rcx, rcx);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+      masm.lea(rdi, Address(rdi, rcx, Address::times_1));
+      masm.lea(rsi, Address(rsi, rcx, Address::times_1));
+      masm.negl(rcx);
+
+      masm.bind(COMPARE_WIDE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1));
+      masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+      masm.jccb(Assembler::notZero, RET_FALSE);
+      masm.addl(rcx, 16);
+      masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+      masm.bind(COMPARE_TAIL);
+      masm.movl(rcx, rax);
+      // Fallthru to tail compare
+    }
+
+    // Compare 4-byte vectors
+    masm.andl(rcx, 0xfffffffc);  // vector count (in bytes)
+    masm.andl(rax, 0x00000002);  // tail char (in bytes)
+    masm.testl(rcx, rcx);
+    masm.jccb(Assembler::zero, COMPARE_CHAR);
+    masm.lea(rdi, Address(rdi, rcx, Address::times_1));
+    masm.lea(rsi, Address(rsi, rcx, Address::times_1));
+    masm.negl(rcx);
+
+    masm.bind(COMPARE_VECTORS);
+    masm.movl(rbx, Address(rdi, rcx, Address::times_1));
+    masm.cmpl(rbx, Address(rsi, rcx, Address::times_1));
+    masm.jccb(Assembler::notEqual, RET_FALSE);
+    masm.addl(rcx, 4);
+    masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+
+    // Compare trailing char (final 2 bytes), if any
+    masm.bind(COMPARE_CHAR);
+    masm.testl(rax, rax);
+    masm.jccb(Assembler::zero, RET_TRUE);
+    masm.load_unsigned_short(rbx, Address(rdi, 0));
+    masm.load_unsigned_short(rcx, Address(rsi, 0));
+    masm.cmpl(rbx, rcx);
+    masm.jccb(Assembler::notEqual, RET_FALSE);
+
+    masm.bind(RET_TRUE);
+    masm.movl(rax, 1);   // return true
+    masm.jmpb(DONE);
+
+    masm.bind(RET_FALSE);
+    masm.xorl(rax, rax); // return false
+
+    masm.bind(DONE);
+    %}
+
+ enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
+                        eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{
+    // SSE4.2 version
+    Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
+          SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
     MacroAssembler masm(&cbuf);
 
-    Register ary1Reg   = as_Register($ary1$$reg);
-    Register ary2Reg   = as_Register($ary2$$reg);
-    Register tmp1Reg   = as_Register($tmp1$$reg);
-    Register tmp2Reg   = as_Register($tmp2$$reg);
-    Register resultReg = as_Register($result$$reg);
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+
+    // Get the first character position in both strings
+    //         [8] char array, [12] offset, [16] count
+    int value_offset  = java_lang_String::value_offset_in_bytes();
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    int count_offset  = java_lang_String::count_offset_in_bytes();
+    int base_offset   = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // Get counts for string and substr
+    masm.movl(rdx, Address(rsi, count_offset));
+    masm.movl(rax, Address(rdi, count_offset));
+    // Check for substr count > string count
+    masm.cmpl(rax, rdx);
+    masm.jcc(Assembler::greater, RET_NEG_ONE);
+
+    // Start the indexOf operation
+    // Get start addr of string
+    masm.movptr(rbx, Address(rsi, value_offset));
+    masm.movl(rcx, Address(rsi, offset_offset));
+    masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
+    masm.push(rsi);
+
+    // Get start addr of substr
+    masm.movptr(rbx, Address(rdi, value_offset));
+    masm.movl(rcx, Address(rdi, offset_offset));
+    masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
+    masm.push(rdi);
+    masm.push(rax);
+    masm.jmpb(PREP_FOR_SCAN);
+
+    // Substr count saved at sp
+    // Substr saved at sp+4
+    // String saved at sp+8
+
+    // Prep to load substr for scan
+    masm.bind(LOAD_SUBSTR);
+    masm.movptr(rdi, Address(rsp, 4));
+    masm.movl(rax, Address(rsp, 0));
+
+    // Load substr
+    masm.bind(PREP_FOR_SCAN);
+    masm.movdqu(tmp1Reg, Address(rdi, 0));
+    masm.addl(rdx, 8);        // prime the loop
+    masm.subptr(rsi, 16);
+
+    // Scan string for substr in 16-byte vectors
+    masm.bind(SCAN_TO_SUBSTR);
+    masm.subl(rdx, 8);
+    masm.addptr(rsi, 16);
+    masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
+    masm.jcc(Assembler::above, SCAN_TO_SUBSTR);     // CF == 0 && ZF == 0
+    masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0
+
+    // Fallthru: found a potential substr
+
+    // Make sure string is still long enough
+    masm.subl(rdx, rcx);
+    masm.cmpl(rdx, rax);
+    masm.jccb(Assembler::negative, RET_NOT_FOUND);
+    // Compute start addr of substr
+    masm.lea(rsi, Address(rsi, rcx, Address::times_2));
+    masm.movptr(rbx, rsi);
+
+    // Compare potential substr
+    masm.addl(rdx, 8);        // prime the loop
+    masm.addl(rax, 8);
+    masm.subptr(rsi, 16);
+    masm.subptr(rdi, 16);
+
+    // Scan 16-byte vectors of string and substr
+    masm.bind(SCAN_SUBSTR);
+    masm.subl(rax, 8);
+    masm.subl(rdx, 8);
+    masm.addptr(rsi, 16);
+    masm.addptr(rdi, 16);
+    masm.movdqu(tmp1Reg, Address(rdi, 0));
+    masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
+    masm.jcc(Assembler::noOverflow, LOAD_SUBSTR);   // OF == 0
+    masm.jcc(Assembler::positive, SCAN_SUBSTR);     // SF == 0
+
+    // Compute substr offset
+    masm.movptr(rsi, Address(rsp, 8));
+    masm.subptr(rbx, rsi);
+    masm.shrl(rbx, 1);
+    masm.jmpb(CLEANUP);
+
+    masm.bind(RET_NEG_ONE);
+    masm.movl(rbx, -1);
+    masm.jmpb(DONE);
+
+    masm.bind(RET_NOT_FOUND);
+    masm.movl(rbx, -1);
+
+    masm.bind(CLEANUP);
+    masm.addptr(rsp, 12);
+
+    masm.bind(DONE);
+  %}
+
+  enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2,
+                             eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{
+    Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
+    MacroAssembler masm(&cbuf);
+
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+    Register ary1Reg      = as_Register($ary1$$reg);
+    Register ary2Reg      = as_Register($ary2$$reg);
+    Register tmp3Reg      = as_Register($tmp3$$reg);
+    Register tmp4Reg      = as_Register($tmp4$$reg);
+    Register resultReg    = as_Register($result$$reg);
 
     int length_offset  = arrayOopDesc::length_offset_in_bytes();
     int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
 
     // Check the input args
-    masm.cmpl(ary1Reg, ary2Reg);
+    masm.cmpptr(ary1Reg, ary2Reg);
     masm.jcc(Assembler::equal, TRUE_LABEL);
-    masm.testl(ary1Reg, ary1Reg);
+    masm.testptr(ary1Reg, ary1Reg);
     masm.jcc(Assembler::zero, FALSE_LABEL);
-    masm.testl(ary2Reg, ary2Reg);
+    masm.testptr(ary2Reg, ary2Reg);
     masm.jcc(Assembler::zero, FALSE_LABEL);
 
     // Check the lengths
-    masm.movl(tmp2Reg, Address(ary1Reg, length_offset));
+    masm.movl(tmp4Reg, Address(ary1Reg, length_offset));
     masm.movl(resultReg, Address(ary2Reg, length_offset));
-    masm.cmpl(tmp2Reg, resultReg);
+    masm.cmpl(tmp4Reg, resultReg);
     masm.jcc(Assembler::notEqual, FALSE_LABEL);
     masm.testl(resultReg, resultReg);
     masm.jcc(Assembler::zero, TRUE_LABEL);
 
-    // Get the number of 4 byte vectors to compare
-    masm.shrl(resultReg, 1);
-
-    // Check for odd-length arrays
-    masm.andl(tmp2Reg, 1);
-    masm.testl(tmp2Reg, tmp2Reg);
-    masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
-
-    // Compare 2-byte "tail" at end of arrays
-    masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
-    masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
-    masm.cmpl(tmp1Reg, tmp2Reg);
-    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    // Load array addrs
+    masm.lea(ary1Reg, Address(ary1Reg, base_offset));
+    masm.lea(ary2Reg, Address(ary2Reg, base_offset));
+
+    // Set byte count
+    masm.shll(tmp4Reg, 1);
+    masm.movl(resultReg, tmp4Reg);
+
+    if (UseSSE42Intrinsics) {
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+      // Compare 16-byte vectors
+      masm.andl(tmp4Reg, 0xfffffff0);    // vector count (in bytes)
+      masm.andl(resultReg, 0x0000000e);  // tail count (in bytes)
+      masm.testl(tmp4Reg, tmp4Reg);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+      masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+      masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+      masm.negl(tmp4Reg);
+
+      masm.bind(COMPARE_WIDE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+      masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+
+      masm.jccb(Assembler::notZero, FALSE_LABEL);
+      masm.addl(tmp4Reg, 16);
+      masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+      masm.bind(COMPARE_TAIL);
+      masm.movl(tmp4Reg, resultReg);
+      // Fallthru to tail compare
+    }
+
+    // Compare 4-byte vectors
+    masm.andl(tmp4Reg, 0xfffffffc);    // vector count (in bytes)
+    masm.andl(resultReg, 0x00000002);  // tail char (in bytes)
+    masm.testl(tmp4Reg, tmp4Reg);
+    masm.jccb(Assembler::zero, COMPARE_CHAR);
+    masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+    masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+    masm.negl(tmp4Reg);
+
+    masm.bind(COMPARE_VECTORS);
+    masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+    masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+    masm.jccb(Assembler::notEqual, FALSE_LABEL);
+    masm.addl(tmp4Reg, 4);
+    masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+
+    // Compare trailing char (final 2 bytes), if any
+    masm.bind(COMPARE_CHAR);
     masm.testl(resultReg, resultReg);
-    masm.jcc(Assembler::zero, TRUE_LABEL);
-
-    // Setup compare loop
-    masm.bind(COMPARE_LOOP_HDR);
-    // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays
-    masm.leal(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
-    masm.leal(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
-    masm.negl(resultReg);
-
-    // 4-byte-wide compare loop
-    masm.bind(COMPARE_LOOP);
-    masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0));
-    masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0));
-    masm.cmpl(ary1Reg, ary2Reg);
-    masm.jcc(Assembler::notEqual, FALSE_LABEL);
-    masm.increment(resultReg);
-    masm.jcc(Assembler::notZero, COMPARE_LOOP);
+    masm.jccb(Assembler::zero, TRUE_LABEL);
+    masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0));
+    masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0));
+    masm.cmpl(tmp3Reg, tmp4Reg);
+    masm.jccb(Assembler::notEqual, FALSE_LABEL);
 
     masm.bind(TRUE_LABEL);
     masm.movl(resultReg, 1);   // return true
-    masm.jmp(DONE_LABEL);
+    masm.jmpb(DONE);
 
     masm.bind(FALSE_LABEL);
     masm.xorl(resultReg, resultReg); // return false
 
     // That's it
-    masm.bind(DONE_LABEL);
+    masm.bind(DONE);
   %}
 
   enc_class enc_pop_rdx() %{
@@ -4288,24 +4570,6 @@
     emit_opcode(cbuf, 0xC8 + $src2$$reg);
   %}
 
-  enc_class enc_membar_acquire %{
-    // Doug Lea believes this is not needed with current Sparcs and TSO.
-    // MacroAssembler masm(&cbuf);
-    // masm.membar();
-  %}
-
-  enc_class enc_membar_release %{
-    // Doug Lea believes this is not needed with current Sparcs and TSO.
-    // MacroAssembler masm(&cbuf);
-    // masm.membar();
-  %}
-
-  enc_class enc_membar_volatile %{
-    MacroAssembler masm(&cbuf);
-    masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad |
-                                            Assembler::StoreStore));
-  %}
-
   // Atomically load the volatile long
   enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{
     emit_opcode(cbuf,0xDF);
@@ -7498,9 +7762,9 @@
   ins_cost(400);
 
   size(0);
-  format %{ "MEMBAR-acquire" %}
-  ins_encode( enc_membar_acquire );
-  ins_pipe(pipe_slow);
+  format %{ "MEMBAR-acquire ! (empty encoding)" %}
+  ins_encode();
+  ins_pipe(empty);
 %}
 
 instruct membar_acquire_lock() %{
@@ -7519,9 +7783,9 @@
   ins_cost(400);
 
   size(0);
-  format %{ "MEMBAR-release" %}
-  ins_encode( enc_membar_release );
-  ins_pipe(pipe_slow);
+  format %{ "MEMBAR-release ! (empty encoding)" %}
+  ins_encode( );
+  ins_pipe(empty);
 %}
 
 instruct membar_release_lock() %{
@@ -7535,12 +7799,22 @@
   ins_pipe(empty);
 %}
 
-instruct membar_volatile() %{
+instruct membar_volatile(eFlagsReg cr) %{
   match(MemBarVolatile);
+  effect(KILL cr);
   ins_cost(400);
 
-  format %{ "MEMBAR-volatile" %}
-  ins_encode( enc_membar_volatile );
+  format %{ 
+    $$template
+    if (os::is_MP()) {
+      $$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile"
+    } else {
+      $$emit$$"MEMBAR-volatile ! (empty encoding)"
+    }
+  %}
+  ins_encode %{
+    __ membar(Assembler::StoreLoad);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -12082,11 +12356,8 @@
   ins_pipe( fpu_reg_reg );
 %}
 
-
-
 // =======================================================================
 // fast clearing of an array
-
 instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
   match(Set dummy (ClearArray cnt base));
   effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
@@ -12100,24 +12371,48 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct string_compare(eDIRegP str1, eSIRegP str2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{
+instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
+                        eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{
   match(Set result (StrComp str1 str2));
-  effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL cr);
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
   //ins_cost(300);
 
   format %{ "String Compare $str1,$str2 -> $result    // KILL EAX, EBX" %}
-  ins_encode( enc_String_Compare() );
+  ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
+  ins_pipe( pipe_slow );
+%}
+
+// fast string equals
+instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
+                       eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
+  match(Set result (StrEquals str1 str2));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
+
+  format %{ "String Equals $str1,$str2 -> $result    // KILL EBX, ECX" %}
+  ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) );
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
+                        eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics);
+  match(Set result (StrIndexOf str1 str2));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
+
+  format %{ "String IndexOf $str1,$str2 -> $result    // KILL EAX, ECX, EDX" %}
+  ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
   ins_pipe( pipe_slow );
 %}
 
 // fast array equals
-instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{
+instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3,
+                      eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
   match(Set result (AryEq ary1 ary2));
-  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr);
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
   //ins_cost(300);
 
-  format %{ "Array Equals $ary1,$ary2 -> $result    // KILL EAX, EBX" %}
-  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) );
+  format %{ "Array Equals $ary1,$ary2 -> $result    // KILL EBX, EDX" %}
+  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
   ins_pipe( pipe_slow );
 %}
 
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 16:50:32 2017 +0200
@@ -3694,13 +3694,16 @@
     }
   %}
 
-  enc_class enc_String_Compare()
-  %{
+  enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
+                        rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{
     Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL,
           POP_LABEL, DONE_LABEL, CONT_LABEL,
           WHILE_HEAD_LABEL;
     MacroAssembler masm(&cbuf);
 
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+
     // Get the first character position in both strings
     //         [8] char array, [12] offset, [16] count
     int value_offset  = java_lang_String::value_offset_in_bytes();
@@ -3718,6 +3721,7 @@
     // Compute the minimum of the string lengths(rsi) and the
     // difference of the string lengths (stack)
 
+    // do the conditional move stuff
     masm.movl(rdi, Address(rdi, count_offset));
     masm.movl(rsi, Address(rsi, count_offset));
     masm.movl(rcx, rdi);
@@ -3745,7 +3749,7 @@
       Label LSkip2;
       // Check if the strings start at same location
       masm.cmpptr(rbx, rax);
-      masm.jcc(Assembler::notEqual, LSkip2);
+      masm.jccb(Assembler::notEqual, LSkip2);
 
       // Check if the length difference is zero (from stack)
       masm.cmpl(Address(rsp, 0), 0x0);
@@ -3755,9 +3759,52 @@
       masm.bind(LSkip2);
     }
 
+    // Advance to next character
+    masm.addptr(rax, 2);
+    masm.addptr(rbx, 2);
+
+    if (UseSSE42Intrinsics) {
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
+      // Setup to compare 16-byte vectors
+      masm.movl(rdi, rsi);
+      masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
+      masm.andl(rdi, 0x00000007); // rdi holds the tail count
+      masm.testl(rsi, rsi);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+
+      masm.lea(rax, Address(rax, rsi, Address::times_2));
+      masm.lea(rbx, Address(rbx, rsi, Address::times_2));
+      masm.negptr(rsi);
+
+      masm.bind(COMPARE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
+      masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+      masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
+      masm.addptr(rsi, 8);
+      masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+      masm.jmpb(COMPARE_TAIL);
+
+      // Mismatched characters in the vectors
+      masm.bind(VECTOR_NOT_EQUAL);
+      masm.lea(rax, Address(rax, rsi, Address::times_2));
+      masm.lea(rbx, Address(rbx, rsi, Address::times_2));
+      masm.movl(rdi, 8);
+
+      // Compare tail (< 8 chars), or rescan last vectors to
+      // find 1st mismatched characters
+      masm.bind(COMPARE_TAIL);
+      masm.testl(rdi, rdi);
+      masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
+      masm.movl(rsi, rdi);
+      // Fallthru to tail compare
+    }
+
     // Shift RAX and RBX to the end of the arrays, negate min
-    masm.lea(rax, Address(rax, rsi, Address::times_2, 2));
-    masm.lea(rbx, Address(rbx, rsi, Address::times_2, 2));
+    masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
+    masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
     masm.negptr(rsi);
 
     // Compare the rest of the characters
@@ -3765,93 +3812,329 @@
     masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
     masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
     masm.subl(rcx, rdi);
-    masm.jcc(Assembler::notZero, POP_LABEL);
+    masm.jccb(Assembler::notZero, POP_LABEL);
     masm.increment(rsi);
     masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
 
     // Strings are equal up to min length.  Return the length difference.
     masm.bind(LENGTH_DIFF_LABEL);
     masm.pop(rcx);
-    masm.jmp(DONE_LABEL);
+    masm.jmpb(DONE_LABEL);
 
     // Discard the stored length difference
     masm.bind(POP_LABEL);
     masm.addptr(rsp, 8);
-       
+
     // That's it
     masm.bind(DONE_LABEL);
   %}
 
-  enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{
-    Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP;
+ enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
+                        rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{
+    // SSE4.2 version
+    Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
+          SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
     MacroAssembler masm(&cbuf);
 
-    Register ary1Reg   = as_Register($ary1$$reg);
-    Register ary2Reg   = as_Register($ary2$$reg);
-    Register tmp1Reg   = as_Register($tmp1$$reg);
-    Register tmp2Reg   = as_Register($tmp2$$reg);
-    Register resultReg = as_Register($result$$reg);
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+
+    // Get the first character position in both strings
+    //         [8] char array, [12] offset, [16] count
+    int value_offset  = java_lang_String::value_offset_in_bytes();
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    int count_offset  = java_lang_String::count_offset_in_bytes();
+    int base_offset   = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // Get counts for string and substr
+    masm.movl(rdx, Address(rsi, count_offset));
+    masm.movl(rax, Address(rdi, count_offset));
+    // Check for substr count > string count
+    masm.cmpl(rax, rdx);
+    masm.jcc(Assembler::greater, RET_NEG_ONE);
+
+    // Start the indexOf operation
+    // Get start addr of string
+    masm.load_heap_oop(rbx, Address(rsi, value_offset));
+    masm.movl(rcx, Address(rsi, offset_offset));
+    masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
+    masm.push(rsi);
+
+    // Get start addr of substr
+    masm.load_heap_oop(rbx, Address(rdi, value_offset));
+    masm.movl(rcx, Address(rdi, offset_offset));
+    masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
+    masm.push(rdi);
+    masm.push(rax);
+    masm.jmpb(PREP_FOR_SCAN);
+
+    // Substr count saved at sp
+    // Substr saved at sp+8
+    // String saved at sp+16
+
+    // Prep to load substr for scan
+    masm.bind(LOAD_SUBSTR);
+    masm.movptr(rdi, Address(rsp, 8));
+    masm.movl(rax, Address(rsp, 0));
+
+    // Load substr
+    masm.bind(PREP_FOR_SCAN);
+    masm.movdqu(tmp1Reg, Address(rdi, 0));
+    masm.addq(rdx, 8);    // prime the loop
+    masm.subptr(rsi, 16);
+
+    // Scan string for substr in 16-byte vectors
+    masm.bind(SCAN_TO_SUBSTR);
+    masm.subq(rdx, 8);
+    masm.addptr(rsi, 16);
+    masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
+    masm.jcc(Assembler::above, SCAN_TO_SUBSTR);
+    masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND);
+
+    // Fallthru: found a potential substr
+
+    //Make sure string is still long enough
+    masm.subl(rdx, rcx);
+    masm.cmpl(rdx, rax);
+    masm.jccb(Assembler::negative, RET_NOT_FOUND);
+    // Compute start addr of substr
+    masm.lea(rsi, Address(rsi, rcx, Address::times_2));
+    masm.movptr(rbx, rsi);
+
+    // Compare potential substr
+    masm.addq(rdx, 8);        // prime the loop
+    masm.addq(rax, 8);
+    masm.subptr(rsi, 16);
+    masm.subptr(rdi, 16);
+
+    // Scan 16-byte vectors of string and substr
+    masm.bind(SCAN_SUBSTR);
+    masm.subq(rax, 8);
+    masm.subq(rdx, 8);
+    masm.addptr(rsi, 16);
+    masm.addptr(rdi, 16);
+    masm.movdqu(tmp1Reg, Address(rdi, 0));
+    masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
+    masm.jcc(Assembler::noOverflow, LOAD_SUBSTR);   // OF == 0
+    masm.jcc(Assembler::positive, SCAN_SUBSTR);     // SF == 0
+
+    // Compute substr offset
+    masm.movptr(rsi, Address(rsp, 16));
+    masm.subptr(rbx, rsi);
+    masm.shrl(rbx, 1);
+    masm.jmpb(CLEANUP);
+
+    masm.bind(RET_NEG_ONE);
+    masm.movl(rbx, -1);
+    masm.jmpb(DONE);
+
+    masm.bind(RET_NOT_FOUND);
+    masm.movl(rbx, -1);
+
+    masm.bind(CLEANUP);
+    masm.addptr(rsp, 24);
+
+    masm.bind(DONE);
+  %}
+
+  enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
+                              rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{
+    Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
+    MacroAssembler masm(&cbuf);
+
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+
+    int value_offset  = java_lang_String::value_offset_in_bytes();
+    int offset_offset = java_lang_String::offset_offset_in_bytes();
+    int count_offset  = java_lang_String::count_offset_in_bytes();
+    int base_offset   = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // does source == target string?
+    masm.cmpptr(rdi, rsi);
+    masm.jcc(Assembler::equal, RET_TRUE);
+
+    // get and compare counts
+    masm.movl(rcx, Address(rdi, count_offset));
+    masm.movl(rax, Address(rsi, count_offset));
+    masm.cmpl(rcx, rax);
+    masm.jcc(Assembler::notEqual, RET_FALSE);
+    masm.testl(rax, rax);
+    masm.jcc(Assembler::zero, RET_TRUE);
+
+    // get source string offset and value
+    masm.load_heap_oop(rbx, Address(rsi, value_offset));
+    masm.movl(rax, Address(rsi, offset_offset));
+    masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset));
+
+    // get compare string offset and value
+    masm.load_heap_oop(rbx, Address(rdi, value_offset));
+    masm.movl(rax, Address(rdi, offset_offset));
+    masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset));
+
+    // Set byte count
+    masm.shll(rcx, 1);
+    masm.movl(rax, rcx);
+
+    if (UseSSE42Intrinsics) {
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+      // Compare 16-byte vectors
+      masm.andl(rcx, 0xfffffff0);  // vector count (in bytes)
+      masm.andl(rax, 0x0000000e);  // tail count (in bytes)
+      masm.testl(rcx, rcx);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+      masm.lea(rdi, Address(rdi, rcx, Address::times_1));
+      masm.lea(rsi, Address(rsi, rcx, Address::times_1));
+      masm.negptr(rcx);
+
+      masm.bind(COMPARE_WIDE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1));
+      masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+      masm.jccb(Assembler::notZero, RET_FALSE);
+      masm.addptr(rcx, 16);
+      masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+      masm.bind(COMPARE_TAIL);
+      masm.movl(rcx, rax);
+      // Fallthru to tail compare
+    }
+
+    // Compare 4-byte vectors
+    masm.andl(rcx, 0xfffffffc);  // vector count (in bytes)
+    masm.andl(rax, 0x00000002);  // tail char (in bytes)
+    masm.testl(rcx, rcx);
+    masm.jccb(Assembler::zero, COMPARE_CHAR);
+    masm.lea(rdi, Address(rdi, rcx, Address::times_1));
+    masm.lea(rsi, Address(rsi, rcx, Address::times_1));
+    masm.negptr(rcx);
+
+    masm.bind(COMPARE_VECTORS);
+    masm.movl(rbx, Address(rdi, rcx, Address::times_1));
+    masm.cmpl(rbx, Address(rsi, rcx, Address::times_1));
+    masm.jccb(Assembler::notEqual, RET_FALSE);
+    masm.addptr(rcx, 4);
+    masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+
+    // Compare trailing char (final 2 bytes), if any
+    masm.bind(COMPARE_CHAR);
+    masm.testl(rax, rax);
+    masm.jccb(Assembler::zero, RET_TRUE);
+    masm.load_unsigned_short(rbx, Address(rdi, 0));
+    masm.load_unsigned_short(rcx, Address(rsi, 0));
+    masm.cmpl(rbx, rcx);
+    masm.jccb(Assembler::notEqual, RET_FALSE);
+
+    masm.bind(RET_TRUE);
+    masm.movl(rax, 1);   // return true
+    masm.jmpb(DONE);
+
+    masm.bind(RET_FALSE);
+    masm.xorl(rax, rax); // return false
+
+    masm.bind(DONE);
+  %}
+
+  enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2,
+                             rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{
+    Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
+    MacroAssembler masm(&cbuf);
+
+    XMMRegister tmp1Reg   = as_XMMRegister($tmp1$$reg);
+    XMMRegister tmp2Reg   = as_XMMRegister($tmp2$$reg);
+    Register ary1Reg      = as_Register($ary1$$reg);
+    Register ary2Reg      = as_Register($ary2$$reg);
+    Register tmp3Reg      = as_Register($tmp3$$reg);
+    Register tmp4Reg      = as_Register($tmp4$$reg);
+    Register resultReg    = as_Register($result$$reg);
 
     int length_offset  = arrayOopDesc::length_offset_in_bytes();
     int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
 
     // Check the input args
-    masm.cmpq(ary1Reg, ary2Reg);                        
+    masm.cmpq(ary1Reg, ary2Reg);
     masm.jcc(Assembler::equal, TRUE_LABEL);
-    masm.testq(ary1Reg, ary1Reg);                       
+    masm.testq(ary1Reg, ary1Reg);
     masm.jcc(Assembler::zero, FALSE_LABEL);
-    masm.testq(ary2Reg, ary2Reg);                       
+    masm.testq(ary2Reg, ary2Reg);
     masm.jcc(Assembler::zero, FALSE_LABEL);
 
     // Check the lengths
-    masm.movl(tmp2Reg, Address(ary1Reg, length_offset));
+    masm.movl(tmp4Reg, Address(ary1Reg, length_offset));
     masm.movl(resultReg, Address(ary2Reg, length_offset));
-    masm.cmpl(tmp2Reg, resultReg);
+    masm.cmpl(tmp4Reg, resultReg);
     masm.jcc(Assembler::notEqual, FALSE_LABEL);
     masm.testl(resultReg, resultReg);
     masm.jcc(Assembler::zero, TRUE_LABEL);
 
-    // Get the number of 4 byte vectors to compare
-    masm.shrl(resultReg, 1);
-
-    // Check for odd-length arrays
-    masm.andl(tmp2Reg, 1);
-    masm.testl(tmp2Reg, tmp2Reg);
-    masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
-
-    // Compare 2-byte "tail" at end of arrays
-    masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
-    masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
-    masm.cmpl(tmp1Reg, tmp2Reg);
-    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    //load array address
+    masm.lea(ary1Reg, Address(ary1Reg, base_offset));
+    masm.lea(ary2Reg, Address(ary2Reg, base_offset));
+
+    //set byte count
+    masm.shll(tmp4Reg, 1);
+    masm.movl(resultReg,tmp4Reg);
+
+    if (UseSSE42Intrinsics){
+      // With SSE4.2, use double quad vector compare
+      Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+      // Compare 16-byte vectors
+      masm.andl(tmp4Reg, 0xfffffff0);    // vector count (in bytes)
+      masm.andl(resultReg, 0x0000000e);  // tail count (in bytes)
+      masm.testl(tmp4Reg, tmp4Reg);
+      masm.jccb(Assembler::zero, COMPARE_TAIL);
+      masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+      masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+      masm.negptr(tmp4Reg);
+
+      masm.bind(COMPARE_WIDE_VECTORS);
+      masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+      masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+      masm.pxor(tmp1Reg, tmp2Reg);
+      masm.ptest(tmp1Reg, tmp1Reg);
+
+      masm.jccb(Assembler::notZero, FALSE_LABEL);
+      masm.addptr(tmp4Reg, 16);
+      masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+      masm.bind(COMPARE_TAIL);
+      masm.movl(tmp4Reg, resultReg);
+      // Fallthru to tail compare
+    }
+
+   // Compare 4-byte vectors
+    masm.andl(tmp4Reg, 0xfffffffc);    // vector count (in bytes)
+    masm.andl(resultReg, 0x00000002);  // tail char (in bytes)
+    masm.testl(tmp4Reg, tmp4Reg); //if tmp2 == 0, only compare char
+    masm.jccb(Assembler::zero, COMPARE_CHAR);
+    masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+    masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+    masm.negptr(tmp4Reg);
+
+    masm.bind(COMPARE_VECTORS);
+    masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
+    masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
+    masm.jccb(Assembler::notEqual, FALSE_LABEL);
+    masm.addptr(tmp4Reg, 4);
+    masm.jcc(Assembler::notZero, COMPARE_VECTORS);
+
+    // Compare trailing char (final 2 bytes), if any
+    masm.bind(COMPARE_CHAR);
     masm.testl(resultReg, resultReg);
-    masm.jcc(Assembler::zero, TRUE_LABEL);
-
-    // Setup compare loop
-    masm.bind(COMPARE_LOOP_HDR);
-    // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays
-    masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
-    masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
-    masm.negq(resultReg);
-
-    // 4-byte-wide compare loop
-    masm.bind(COMPARE_LOOP);
-    masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0));
-    masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0));
-    masm.cmpl(ary1Reg, ary2Reg);
-    masm.jcc(Assembler::notEqual, FALSE_LABEL);
-    masm.incrementq(resultReg);
-    masm.jcc(Assembler::notZero, COMPARE_LOOP);
+    masm.jccb(Assembler::zero, TRUE_LABEL);
+    masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0));
+    masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0));
+    masm.cmpl(tmp3Reg, tmp4Reg);
+    masm.jccb(Assembler::notEqual, FALSE_LABEL);
 
     masm.bind(TRUE_LABEL);
     masm.movl(resultReg, 1);   // return true
-    masm.jmp(DONE_LABEL);
+    masm.jmpb(DONE);
 
     masm.bind(FALSE_LABEL);
     masm.xorl(resultReg, resultReg); // return false
 
     // That's it
-    masm.bind(DONE_LABEL);
+    masm.bind(DONE);
   %}
 
   enc_class enc_rethrow()
@@ -4162,33 +4445,6 @@
     // done:
   %}
 
-  enc_class enc_membar_acquire
-  %{
-    // [jk] not needed currently, if you enable this and it really
-    // emits code don't forget to the remove the "size(0)" line in
-    // membar_acquire()
-    // MacroAssembler masm(&cbuf);
-    // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore |
-    //                                         Assembler::LoadLoad));
-  %}
-
-  enc_class enc_membar_release
-  %{
-    // [jk] not needed currently, if you enable this and it really
-    // emits code don't forget to the remove the "size(0)" line in
-    // membar_release()
-    // MacroAssembler masm(&cbuf);
-    // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore |
-    //                                         Assembler::StoreStore));
-  %}
-
-  enc_class enc_membar_volatile
-  %{
-    MacroAssembler masm(&cbuf);
-    masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad |
-                                            Assembler::StoreStore));
-  %}
-
   // Safepoint Poll.  This polls the safepoint page, and causes an
   // exception if it is not readable. Unfortunately, it kills
   // RFLAGS in the process.
@@ -5114,7 +5370,7 @@
 %}
 
 // Double register operands
-operand regD()
+operand regD() 
 %{
   constraint(ALLOC_IN_RC(double_reg));
   match(RegD);
@@ -7458,7 +7714,7 @@
   ins_cost(0);
 
   size(0);
-  format %{ "MEMBAR-acquire" %}
+  format %{ "MEMBAR-acquire ! (empty encoding)" %}
   ins_encode();
   ins_pipe(empty);
 %}
@@ -7481,7 +7737,7 @@
   ins_cost(0);
 
   size(0);
-  format %{ "MEMBAR-release" %}
+  format %{ "MEMBAR-release ! (empty encoding)" %}
   ins_encode();
   ins_pipe(empty);
 %}
@@ -7498,13 +7754,22 @@
   ins_pipe(empty);
 %}
 
-instruct membar_volatile()
-%{
+instruct membar_volatile(rFlagsReg cr) %{
   match(MemBarVolatile);
+  effect(KILL cr);
   ins_cost(400);
 
-  format %{ "MEMBAR-volatile" %}
-  ins_encode(enc_membar_volatile);
+  format %{ 
+    $$template
+    if (os::is_MP()) {
+      $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
+    } else {
+      $$emit$$"MEMBAR-volatile ! (empty encoding)"
+    }
+  %}
+  ins_encode %{
+    __ membar(Assembler::StoreLoad);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -11558,27 +11823,52 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct string_compare(rdi_RegP str1, rsi_RegP str2, rax_RegI tmp1,
-                        rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr)
+instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
+                        rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
 %{
   match(Set result (StrComp str1 str2));
-  effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL cr);
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
   //ins_cost(300);
 
   format %{ "String Compare $str1, $str2 -> $result    // XXX KILL RAX, RBX" %}
-  ins_encode( enc_String_Compare() );
+  ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
+                        rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics);
+  match(Set result (StrIndexOf str1 str2));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
+
+  format %{ "String IndexOf $str1,$str2 -> $result   // KILL RAX, RCX, RDX" %}
+  ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
+  ins_pipe( pipe_slow );
+%}
+
+// fast string equals
+instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3,
+                       rcx_RegI tmp4, rax_RegI result, rFlagsReg cr)
+%{
+  match(Set result (StrEquals str1 str2));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
+
+  format %{ "String Equals $str1,$str2 -> $result    // KILL RBX, RCX" %}
+  ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
   ins_pipe( pipe_slow );
 %}
 
 // fast array equals
-instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, 
-                      rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{
+instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3,
+                      rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
+%{
   match(Set result (AryEq ary1 ary2));
-  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr);
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
   //ins_cost(300);
 
-  format %{ "Array Equals $ary1,$ary2 -> $result    // KILL RAX, RBX" %}
-  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) );
+  format %{ "Array Equals $ary1,$ary2 -> $result   // KILL RAX, RBX" %}
+  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
   ins_pipe( pipe_slow );
 %}
 
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1518,21 +1518,51 @@
 
 const char* os::get_temp_directory() { return "/tmp/"; }
 
-void os::dll_build_name(
-    char* buffer, size_t buflen, const char* pname, const char* fname) {
-  // copied from libhpi
+static bool file_exists(const char* filename) {
+  struct stat statbuf;
+  if (filename == NULL || strlen(filename) == 0) {
+    return false;
+  }
+  return os::stat(filename, &statbuf) == 0;
+}
+
+void os::dll_build_name(char* buffer, size_t buflen,
+                        const char* pname, const char* fname) {
+  // Copied from libhpi
   const size_t pnamelen = pname ? strlen(pname) : 0;
 
-  /* Quietly truncate on buffer overflow.  Should be an error. */
+  // Quietly truncate on buffer overflow.  Should be an error.
   if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
       *buffer = '\0';
       return;
   }
 
   if (pnamelen == 0) {
-      sprintf(buffer, "lib%s.so", fname);
+    snprintf(buffer, buflen, "lib%s.so", fname);
+  } else if (strchr(pname, *os::path_separator()) != NULL) {
+    int n;
+    char** pelements = split_path(pname, &n);
+    for (int i = 0 ; i < n ; i++) {
+      // Really shouldn't be NULL, but check can't hurt
+      if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
+        continue; // skip the empty path values
+      }
+      snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
+      if (file_exists(buffer)) {
+        break;
+      }
+    }
+    // release the storage
+    for (int i = 0 ; i < n ; i++) {
+      if (pelements[i] != NULL) {
+        FREE_C_HEAP_ARRAY(char, pelements[i]);
+      }
+    }
+    if (pelements != NULL) {
+      FREE_C_HEAP_ARRAY(char*, pelements);
+    }
   } else {
-      sprintf(buffer, "%s/lib%s.so", pname, fname);
+    snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
   }
 }
 
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1827,21 +1827,51 @@
 
 const char* os::get_temp_directory() { return "/tmp/"; }
 
-void os::dll_build_name(
-    char* buffer, size_t buflen, const char* pname, const char* fname) {
-  // copied from libhpi
+static bool file_exists(const char* filename) {
+  struct stat statbuf;
+  if (filename == NULL || strlen(filename) == 0) {
+    return false;
+  }
+  return os::stat(filename, &statbuf) == 0;
+}
+
+void os::dll_build_name(char* buffer, size_t buflen,
+                        const char* pname, const char* fname) {
+  // Copied from libhpi
   const size_t pnamelen = pname ? strlen(pname) : 0;
 
-  /* Quietly truncate on buffer overflow.  Should be an error. */
+  // Quietly truncate on buffer overflow.  Should be an error.
   if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
       *buffer = '\0';
       return;
   }
 
   if (pnamelen == 0) {
-      sprintf(buffer, "lib%s.so", fname);
+    snprintf(buffer, buflen, "lib%s.so", fname);
+  } else if (strchr(pname, *os::path_separator()) != NULL) {
+    int n;
+    char** pelements = split_path(pname, &n);
+    for (int i = 0 ; i < n ; i++) {
+      // really shouldn't be NULL but what the heck, check can't hurt
+      if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
+        continue; // skip the empty path values
+      }
+      snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
+      if (file_exists(buffer)) {
+        break;
+      }
+    }
+    // release the storage
+    for (int i = 0 ; i < n ; i++) {
+      if (pelements[i] != NULL) {
+        FREE_C_HEAP_ARRAY(char, pelements[i]);
+      }
+    }
+    if (pelements != NULL) {
+      FREE_C_HEAP_ARRAY(char*, pelements);
+    }
   } else {
-      sprintf(buffer, "%s/lib%s.so", pname, fname);
+    snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
   }
 }
 
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1004,26 +1004,61 @@
     }
 }
 
-void os::dll_build_name(char *holder, size_t holderlen,
-                        const char* pname, const char* fname)
-{
-    // copied from libhpi
-    const size_t pnamelen = pname ? strlen(pname) : 0;
-    const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
-
-    /* Quietly truncates on buffer overflow. Should be an error. */
-    if (pnamelen + strlen(fname) + 10 > holderlen) {
-        *holder = '\0';
-        return;
+static bool file_exists(const char* filename) {
+  if (filename == NULL || strlen(filename) == 0) {
+    return false;
+  }
+  return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
+}
+
+void os::dll_build_name(char *buffer, size_t buflen,
+                        const char* pname, const char* fname) {
+  // Copied from libhpi
+  const size_t pnamelen = pname ? strlen(pname) : 0;
+  const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
+
+  // Quietly truncates on buffer overflow. Should be an error.
+  if (pnamelen + strlen(fname) + 10 > buflen) {
+    *buffer = '\0';
+    return;
+  }
+
+  if (pnamelen == 0) {
+    jio_snprintf(buffer, buflen, "%s.dll", fname);
+  } else if (c == ':' || c == '\\') {
+    jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname);
+  } else if (strchr(pname, *os::path_separator()) != NULL) {
+    int n;
+    char** pelements = split_path(pname, &n);
+    for (int i = 0 ; i < n ; i++) {
+      char* path = pelements[i];
+      // Really shouldn't be NULL, but check can't hurt
+      size_t plen = (path == NULL) ? 0 : strlen(path);
+      if (plen == 0) {
+        continue; // skip the empty path values
+      }
+      const char lastchar = path[plen - 1];
+      if (lastchar == ':' || lastchar == '\\') {
+        jio_snprintf(buffer, buflen, "%s%s.dll", path, fname);
+      } else {
+        jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
+      }
+      if (file_exists(buffer)) {
+        break;
+      }
     }
-
-    if (pnamelen == 0) {
-        sprintf(holder, "%s.dll", fname);
-    } else if (c == ':' || c == '\\') {
-        sprintf(holder, "%s%s.dll", pname, fname);
-    } else {
-        sprintf(holder, "%s\\%s.dll", pname, fname);
+    // release the storage
+    for (int i = 0 ; i < n ; i++) {
+      if (pelements[i] != NULL) {
+        FREE_C_HEAP_ARRAY(char, pelements[i]);
+      }
     }
+    if (pelements != NULL) {
+      FREE_C_HEAP_ARRAY(char*, pelements);
+    }
+  } else {
+    jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
+  }
 }
 
 // Needs to be in os specific directory because windows requires another
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -29,13 +29,11 @@
   static jint  (*atomic_cmpxchg_func)     (jint,  volatile jint*,  jint);
   static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong);
   static jint  (*atomic_add_func)         (jint,  volatile jint*);
-  static void  (*fence_func)              ();
 
   static jint  atomic_xchg_bootstrap        (jint,  volatile jint*);
   static jint  atomic_cmpxchg_bootstrap     (jint,  volatile jint*,  jint);
   static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong);
   static jint  atomic_add_bootstrap         (jint,  volatile jint*);
-  static void  fence_bootstrap              ();
 
   static void setup_fpu() {}
 
--- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -44,11 +44,12 @@
 
 inline void OrderAccess::fence() {
   if (os::is_MP()) {
+    // always use locked addl since mfence is sometimes expensive
 #ifdef AMD64
-    __asm__ __volatile__ ("mfence":::"memory");
+    __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
 #else
     __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
-#endif // AMD64
+#endif
   }
 }
 
--- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -60,22 +60,10 @@
   dummy = 0;
 }
 
-#if defined(COMPILER2) || defined(_LP64)
-
 inline void OrderAccess::fence() {
   _OrderAccess_fence();
 }
 
-#else  // defined(COMPILER2) || defined(_LP64)
-
-inline void OrderAccess::fence() {
-  if (os::is_MP()) {
-    (*os::fence_func)();
-  }
-}
-
-#endif // defined(COMPILER2) || defined(_LP64)
-
 #endif // _GNU_SOURCE
 
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -619,7 +619,6 @@
 typedef jint  cmpxchg_func_t     (jint,  volatile jint*,  jint);
 typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong);
 typedef jint  add_func_t         (jint,  volatile jint*);
-typedef void  fence_func_t       ();
 
 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) {
   // try to use the stub:
@@ -681,25 +680,10 @@
   return (*dest) += add_value;
 }
 
-void os::fence_bootstrap() {
-  // try to use the stub:
-  fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry());
-
-  if (func != NULL) {
-    os::fence_func = func;
-    (*func)();
-    return;
-  }
-  assert(Threads::number_of_threads() == 0, "for bootstrap only");
-
-  // don't have to do anything for a single thread
-}
-
 xchg_func_t*         os::atomic_xchg_func         = os::atomic_xchg_bootstrap;
 cmpxchg_func_t*      os::atomic_cmpxchg_func      = os::atomic_cmpxchg_bootstrap;
 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
 add_func_t*          os::atomic_add_func          = os::atomic_add_bootstrap;
-fence_func_t*        os::fence_func               = os::fence_bootstrap;
 
 #endif // !_LP64 && !COMPILER2
 
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -29,13 +29,11 @@
   static jint  (*atomic_cmpxchg_func)     (jint,  volatile jint*,  jint);
   static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong);
   static jint  (*atomic_add_func)         (jint,  volatile jint*);
-  static void  (*fence_func)              ();
 
   static jint  atomic_xchg_bootstrap        (jint,  volatile jint*);
   static jint  atomic_cmpxchg_bootstrap     (jint,  volatile jint*,  jint);
   static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong);
   static jint  atomic_add_bootstrap         (jint,  volatile jint*);
-  static void  fence_bootstrap              ();
 
   static void setup_fpu() {}
 
--- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -61,11 +61,8 @@
 #endif // AMD64
   }
   inline void _OrderAccess_fence() {
-#ifdef AMD64
-    __asm__ __volatile__ ("mfence":::"memory");
-#else
+    // Always use locked addl since mfence is sometimes expensive
     __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
-#endif // AMD64
   }
 
 }
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -794,7 +794,6 @@
 typedef jint  cmpxchg_func_t     (jint,  volatile jint*,  jint);
 typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong);
 typedef jint  add_func_t         (jint,  volatile jint*);
-typedef void  fence_func_t       ();
 
 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) {
   // try to use the stub:
@@ -856,25 +855,10 @@
   return (*dest) += add_value;
 }
 
-void os::fence_bootstrap() {
-  // try to use the stub:
-  fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry());
-
-  if (func != NULL) {
-    os::fence_func = func;
-    (*func)();
-    return;
-  }
-  assert(Threads::number_of_threads() == 0, "for bootstrap only");
-
-  // don't have to do anything for a single thread
-}
-
 xchg_func_t*         os::atomic_xchg_func         = os::atomic_xchg_bootstrap;
 cmpxchg_func_t*      os::atomic_cmpxchg_func      = os::atomic_cmpxchg_bootstrap;
 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
 add_func_t*          os::atomic_add_func          = os::atomic_add_bootstrap;
-fence_func_t*        os::fence_func               = os::fence_bootstrap;
 
 extern "C" _solaris_raw_setup_fpu(address ptr);
 void os::setup_fpu() {
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -32,13 +32,11 @@
   static jint  (*atomic_cmpxchg_func)     (jint,  volatile jint*,  jint);
   static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong);
   static jint  (*atomic_add_func)         (jint,  volatile jint*);
-  static void  (*fence_func)              ();
 
   static jint  atomic_xchg_bootstrap        (jint,  volatile jint*);
   static jint  atomic_cmpxchg_bootstrap     (jint,  volatile jint*,  jint);
   static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong);
   static jint  atomic_add_bootstrap         (jint,  volatile jint*);
-  static void  fence_bootstrap              ();
 
   static void setup_fpu();
 #endif // AMD64
--- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -46,7 +46,7 @@
 
 inline void OrderAccess::fence() {
 #ifdef AMD64
-  (*os::fence_func)();
+  StubRoutines_fence();
 #else
   if (os::is_MP()) {
     __asm {
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -196,7 +196,6 @@
 typedef jlong     cmpxchg_long_func_t    (jlong,    volatile jlong*, jlong);
 typedef jint      add_func_t             (jint,     volatile jint*);
 typedef intptr_t  add_ptr_func_t         (intptr_t, volatile intptr_t*);
-typedef void      fence_func_t           ();
 
 #ifdef AMD64
 
@@ -292,27 +291,11 @@
   return (*dest) += add_value;
 }
 
-void os::fence_bootstrap() {
-  // try to use the stub:
-  fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry());
-
-  if (func != NULL) {
-    os::fence_func = func;
-    (*func)();
-    return;
-  }
-  assert(Threads::number_of_threads() == 0, "for bootstrap only");
-
-  // don't have to do anything for a single thread
-}
-
-
 xchg_func_t*         os::atomic_xchg_func         = os::atomic_xchg_bootstrap;
 xchg_ptr_func_t*     os::atomic_xchg_ptr_func     = os::atomic_xchg_ptr_bootstrap;
 cmpxchg_func_t*      os::atomic_cmpxchg_func      = os::atomic_cmpxchg_bootstrap;
 add_func_t*          os::atomic_add_func          = os::atomic_add_bootstrap;
 add_ptr_func_t*      os::atomic_add_ptr_func      = os::atomic_add_ptr_bootstrap;
-fence_func_t*        os::fence_func               = os::fence_bootstrap;
 
 #endif // AMD64
 
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -35,9 +35,6 @@
   static jint      (*atomic_add_func)           (jint,      volatile jint*);
   static intptr_t  (*atomic_add_ptr_func)       (intptr_t,  volatile intptr_t*);
 
-  static void      (*fence_func)                ();
-
-
   static jint      atomic_xchg_bootstrap        (jint,      volatile jint*);
   static intptr_t  atomic_xchg_ptr_bootstrap    (intptr_t,  volatile intptr_t*);
 
@@ -53,8 +50,6 @@
 #ifdef AMD64
   static jint      atomic_add_bootstrap         (jint,      volatile jint*);
   static intptr_t  atomic_add_ptr_bootstrap     (intptr_t,  volatile intptr_t*);
-
-  static void      fence_bootstrap              ();
 #endif // AMD64
 
   static void setup_fpu();
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -574,9 +574,13 @@
   // TEMPORARY
   // if( is_simple_chain_rule(globals) )  return false;
 
-  // String-compare uses many memorys edges, but writes none
+  // String.(compareTo/equals/indexOf) and Arrays.equals use many memorys edges,
+  // but writes none
   if( _matrule && _matrule->_rChild &&
-      strcmp(_matrule->_rChild->_opType,"StrComp")==0 )
+      ( strcmp(_matrule->_rChild->_opType,"StrComp"    )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrEquals"  )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 ||
+        strcmp(_matrule->_rChild->_opType,"AryEq"      )==0 ))
     return true;
 
   // Check if instruction has a USE of a memory operand class, but no defs
@@ -815,8 +819,10 @@
     return AdlcVMDeps::Parms;   // Skip the machine-state edges
 
   if( _matrule->_rChild &&
-          strcmp(_matrule->_rChild->_opType,"StrComp")==0 ) {
-        // String compare takes 1 control and 4 memory edges.
+      ( strcmp(_matrule->_rChild->_opType,"StrComp"   )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) {
+        // String.(compareTo/equals/indexOf) take 1 control and 4 memory edges.
     return 5;
   }
 
--- a/hotspot/src/share/vm/asm/assembler.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/asm/assembler.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,15 +143,15 @@
 // A union type for code which has to assemble both constant and
 // non-constant operands, when the distinction cannot be made
 // statically.
-class RegisterConstant VALUE_OBJ_CLASS_SPEC {
+class RegisterOrConstant VALUE_OBJ_CLASS_SPEC {
  private:
   Register _r;
   intptr_t _c;
 
  public:
-  RegisterConstant(): _r(noreg), _c(0) {}
-  RegisterConstant(Register r): _r(r), _c(0) {}
-  RegisterConstant(intptr_t c): _r(noreg), _c(c) {}
+  RegisterOrConstant(): _r(noreg), _c(0) {}
+  RegisterOrConstant(Register r): _r(r), _c(0) {}
+  RegisterOrConstant(intptr_t c): _r(noreg), _c(c) {}
 
   Register as_register() const { assert(is_register(),""); return _r; }
   intptr_t as_constant() const { assert(is_constant(),""); return _c; }
@@ -310,13 +310,13 @@
   // offsets in code which must be generated before the object class is loaded.
   // Field offsets are never zero, since an object's header (mark word)
   // is located at offset zero.
-  RegisterConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) {
-    return delayed_value(delayed_value_addr(value_fn), tmp, offset);
+  RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) {
+    return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
   }
-  RegisterConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) {
-    return delayed_value(delayed_value_addr(value_fn), tmp, offset);
+  RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) {
+    return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
   }
-  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
+  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
   // Last overloading is platform-dependent; look in assembler_<arch>.cpp.
   static intptr_t* delayed_value_addr(int(*constant_fn)());
   static intptr_t* delayed_value_addr(address(*constant_fn)());
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -2237,7 +2237,6 @@
   for (SuccIter iter(tail); !iter.done(); iter.next()) {
     if (iter.succ() == head) {
       iter.set_succ(clone);
-      break;
     }
   }
   flow_block(tail, temp_vector, temp_set);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -239,22 +239,20 @@
   typeArrayOop value  = java_lang_String::value(obj);
   int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
-
-  ResourceMark rm(THREAD);
-  symbolHandle result;
-
-  if (length > 0) {
-    int utf8_length = UNICODE::utf8_length(value->char_at_addr(offset), length);
-    char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
-    UNICODE::convert_to_utf8(value->char_at_addr(offset), length, chars);
-    // Allocate the symbol
-    result = oopFactory::new_symbol_handle(chars, utf8_length, CHECK_(symbolHandle()));
-  } else {
-    result = oopFactory::new_symbol_handle("", 0, CHECK_(symbolHandle()));
-  }
-  return result;
+  jchar* base = value->char_at_addr(offset);
+  symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD);
+  return symbolHandle(THREAD, sym);
 }
 
+symbolOop java_lang_String::as_symbol_or_null(oop java_string) {
+  typeArrayOop value  = java_lang_String::value(java_string);
+  int          offset = java_lang_String::offset(java_string);
+  int          length = java_lang_String::length(java_string);
+  jchar* base = value->char_at_addr(offset);
+  return SymbolTable::probe_unicode(base, length);
+}
+
+
 int java_lang_String::utf8_length(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
@@ -385,6 +383,48 @@
 }
 
 
+void java_lang_Class::print_signature(oop java_class, outputStream* st) {
+  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+  symbolOop name = NULL;
+  bool is_instance = false;
+  if (is_primitive(java_class)) {
+    name = vmSymbols::type_signature(primitive_type(java_class));
+  } else {
+    klassOop k = as_klassOop(java_class);
+    is_instance = Klass::cast(k)->oop_is_instance();
+    name = Klass::cast(k)->name();
+  }
+  if (name == NULL) {
+    st->print("<null>");
+    return;
+  }
+  if (is_instance)  st->print("L");
+  st->write((char*) name->base(), (int) name->utf8_length());
+  if (is_instance)  st->print(";");
+}
+
+symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) {
+  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+  symbolOop name = NULL;
+  if (is_primitive(java_class)) {
+    return vmSymbols::type_signature(primitive_type(java_class));
+  } else {
+    klassOop k = as_klassOop(java_class);
+    if (!Klass::cast(k)->oop_is_instance()) {
+      return Klass::cast(k)->name();
+    } else {
+      ResourceMark rm;
+      const char* sigstr = Klass::cast(k)->signature_name();
+      int         siglen = (int) strlen(sigstr);
+      if (!intern_if_not_found)
+        return SymbolTable::probe(sigstr, siglen);
+      else
+        return oopFactory::new_symbol(sigstr, siglen, THREAD);
+    }
+  }
+}
+
+
 klassOop java_lang_Class::array_klass(oop java_class) {
   klassOop k = klassOop(java_class->obj_field(array_klass_offset));
   assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass");
@@ -412,6 +452,8 @@
 
 
 bool java_lang_Class::is_primitive(oop java_class) {
+  // should assert:
+  //assert(java_lang_Class::is_instance(java_class), "must be a Class object");
   klassOop k = klassOop(java_class->obj_field(klass_offset));
   return k == NULL;
 }
@@ -431,6 +473,19 @@
   return type;
 }
 
+BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klass) {
+  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+  if (is_primitive(java_class)) {
+    if (reference_klass != NULL)
+      (*reference_klass) = NULL;
+    return primitive_type(java_class);
+  } else {
+    if (reference_klass != NULL)
+      (*reference_klass) = as_klassOop(java_class);
+    return T_OBJECT;
+  }
+}
+
 
 oop java_lang_Class::primitive_mirror(BasicType t) {
   oop mirror = Universe::java_mirror(t);
@@ -1988,6 +2043,21 @@
 }
 
 
+void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* st) {
+  switch (type) {
+  case T_BOOLEAN:   st->print("%s", value->z ? "true" : "false");   break;
+  case T_CHAR:      st->print("%d", value->c);                      break;
+  case T_BYTE:      st->print("%d", value->b);                      break;
+  case T_SHORT:     st->print("%d", value->s);                      break;
+  case T_INT:       st->print("%d", value->i);                      break;
+  case T_LONG:      st->print(INT64_FORMAT, value->j);              break;
+  case T_FLOAT:     st->print("%f", value->f);                      break;
+  case T_DOUBLE:    st->print("%lf", value->d);                     break;
+  default:          st->print("type %d?", type);                    break;
+  }
+}
+
+
 // Support for java_lang_ref_Reference
 oop java_lang_ref_Reference::pending_list_lock() {
   instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -107,6 +107,7 @@
 
   // Conversion
   static symbolHandle as_symbol(Handle java_string, TRAPS);
+  static symbolOop as_symbol_or_null(oop java_string);
 
   // Testers
   static bool is_instance(oop obj) {
@@ -149,6 +150,9 @@
   static oop  create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
   // Conversion
   static klassOop as_klassOop(oop java_class);
+  static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
+  static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
+  static void print_signature(oop java_class, outputStream *st);
   // Testing
   static bool is_instance(oop obj) {
     return obj != NULL && obj->klass() == SystemDictionary::class_klass();
@@ -668,6 +672,8 @@
   static BasicType basic_type(oop box);
   static bool is_instance(oop box)                 { return basic_type(box) != T_ILLEGAL; }
   static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; }
+  static void print(oop box, outputStream* st)     { jvalue value;  print(get_value(box, &value), &value, st); }
+  static void print(BasicType type, jvalue* value, outputStream* st);
 
   static int value_offset_in_bytes(BasicType type) {
     return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
--- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,8 +60,10 @@
   bool add_entry(symbolHandle name, klassOop klass1, Handle loader1,
                                     klassOop klass2, Handle loader2);
 
-  void check_signature_loaders(symbolHandle signature, Handle loader1,
-                               Handle loader2, bool is_method, TRAPS);
+  // Note:  The main entry point for this module is via SystemDictionary.
+  // SystemDictionary::check_signature_loaders(symbolHandle signature,
+  //                                           Handle loader1, Handle loader2,
+  //                                           bool is_method, TRAPS)
 
   klassOop find_constrained_klass(symbolHandle name, Handle loader);
   klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name,
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -109,6 +109,40 @@
   return the_table()->lookup(index, name, len, hash);
 }
 
+// Suggestion: Push unicode-based lookup all the way into the hashing
+// and probing logic, so there is no need for convert_to_utf8 until
+// an actual new symbolOop is created.
+symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
+  int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
+  char stack_buf[128];
+  if (utf8_length < (int) sizeof(stack_buf)) {
+    char* chars = stack_buf;
+    UNICODE::convert_to_utf8(name, utf16_length, chars);
+    return lookup(chars, utf8_length, THREAD);
+  } else {
+    ResourceMark rm(THREAD);
+    char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
+    UNICODE::convert_to_utf8(name, utf16_length, chars);
+    return lookup(chars, utf8_length, THREAD);
+  }
+}
+
+symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
+                                           unsigned int& hash) {
+  int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
+  char stack_buf[128];
+  if (utf8_length < (int) sizeof(stack_buf)) {
+    char* chars = stack_buf;
+    UNICODE::convert_to_utf8(name, utf16_length, chars);
+    return lookup_only(chars, utf8_length, hash);
+  } else {
+    ResourceMark rm;
+    char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
+    UNICODE::convert_to_utf8(name, utf16_length, chars);
+    return lookup_only(chars, utf8_length, hash);
+  }
+}
+
 void SymbolTable::add(constantPoolHandle cp, int names_count,
                       const char** names, int* lengths, int* cp_indices,
                       unsigned int* hashValues, TRAPS) {
@@ -126,15 +160,6 @@
   }
 }
 
-// Needed for preloading classes in signatures when compiling.
-
-symbolOop SymbolTable::probe(const char* name, int len) {
-  unsigned int hashValue = hash_symbol(name, len);
-  int index = the_table()->hash_to_index(hashValue);
-  return the_table()->lookup(index, name, len, hashValue);
-}
-
-
 symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
                                  unsigned int hashValue, TRAPS) {
   assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,10 @@
   // Only copy to C string to be added if lookup failed.
   static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS);
 
+  // jchar (utf16) version of lookups
+  static symbolOop lookup_unicode(const jchar* name, int len, TRAPS);
+  static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
+
   static void add(constantPoolHandle cp, int names_count,
                   const char** names, int* lengths, int* cp_indices,
                   unsigned int* hashValues, TRAPS);
@@ -112,7 +116,14 @@
   // Needed for preloading classes in signatures when compiling.
   // Returns the symbol is already present in symbol table, otherwise
   // NULL.  NO ALLOCATION IS GUARANTEED!
-  static symbolOop probe(const char* name, int len);
+  static symbolOop probe(const char* name, int len) {
+    unsigned int ignore_hash;
+    return lookup_only(name, len, ignore_hash);
+  }
+  static symbolOop probe_unicode(const jchar* name, int len) {
+    unsigned int ignore_hash;
+    return lookup_only_unicode(name, len, ignore_hash);
+  }
 
   // Histogram
   static void print_histogram()     PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1964,6 +1964,13 @@
   return T_OBJECT;
 }
 
+KlassHandle SystemDictionaryHandles::box_klass(BasicType t) {
+  if (t >= T_BOOLEAN && t <= T_VOID)
+    return KlassHandle(&SystemDictionary::_box_klasses[t], true);
+  else
+    return KlassHandle();
+}
+
 // Constraints on class loaders. The details of the algorithm can be
 // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
 // Virtual Machine" by Sheng Liang and Gilad Bracha.  The basic idea is
@@ -2174,11 +2181,56 @@
 }
 
 
+// Signature constraints ensure that callers and callees agree about
+// the meaning of type names in their signatures.  This routine is the
+// intake for constraints.  It collects them from several places:
+//
+//  * LinkResolver::resolve_method (if check_access is true) requires
+//    that the resolving class (the caller) and the defining class of
+//    the resolved method (the callee) agree on each type in the
+//    method's signature.
+//
+//  * LinkResolver::resolve_interface_method performs exactly the same
+//    checks.
+//
+//  * LinkResolver::resolve_field requires that the constant pool
+//    attempting to link to a field agree with the field's defining
+//    class about the type of the field signature.
+//
+//  * klassVtable::initialize_vtable requires that, when a class
+//    overrides a vtable entry allocated by a superclass, that the
+//    overriding method (i.e., the callee) agree with the superclass
+//    on each type in the method's signature.
+//
+//  * klassItable::initialize_itable requires that, when a class fills
+//    in its itables, for each non-abstract method installed in an
+//    itable, the method (i.e., the callee) agree with the interface
+//    on each type in the method's signature.
+//
+// All those methods have a boolean (check_access, checkconstraints)
+// which turns off the checks.  This is used from specialized contexts
+// such as bootstrapping, dumping, and debugging.
+//
+// No direct constraint is placed between the class and its
+// supertypes.  Constraints are only placed along linked relations
+// between callers and callees.  When a method overrides or implements
+// an abstract method in a supertype (superclass or interface), the
+// constraints are placed as if the supertype were the caller to the
+// overriding method.  (This works well, since callers to the
+// supertype have already established agreement between themselves and
+// the supertype.)  As a result of all this, a class can disagree with
+// its supertype about the meaning of a type name, as long as that
+// class neither calls a relevant method of the supertype, nor is
+// called (perhaps via an override) from the supertype.
+//
+//
+// SystemDictionary::check_signature_loaders(sig, l1, l2)
+//
 // Make sure all class components (including arrays) in the given
 // signature will be resolved to the same class in both loaders.
 // Returns the name of the type that failed a loader constraint check, or
 // NULL if no constraint failed. The returned C string needs cleaning up
-// with a ResourceMark in the caller
+// with a ResourceMark in the caller.  No exception except OOME is thrown.
 char* SystemDictionary::check_signature_loaders(symbolHandle signature,
                                                Handle loader1, Handle loader2,
                                                bool is_method, TRAPS)  {
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -161,6 +161,7 @@
 class SystemDictionary : AllStatic {
   friend class VMStructs;
   friend class CompactingPermGenGen;
+  friend class SystemDictionaryHandles;
   NOT_PRODUCT(friend class instanceKlassKlass;)
 
  public:
@@ -595,3 +596,18 @@
   static bool _has_loadClassInternal;
   static bool _has_checkPackageAccess;
 };
+
+// Cf. vmSymbols vs. vmSymbolHandles
+class SystemDictionaryHandles : AllStatic {
+public:
+  #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \
+    static KlassHandle name() { \
+      SystemDictionary::name(); \
+      klassOop* loc = &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
+      return KlassHandle(loc, true); \
+    }
+  WK_KLASSES_DO(WK_KLASS_HANDLE_DECLARE);
+  #undef WK_KLASS_HANDLE_DECLARE
+
+  static KlassHandle box_klass(BasicType t);
+};
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -49,6 +49,8 @@
   template(java_lang_Object,                          "java/lang/Object")                         \
   template(java_lang_Class,                           "java/lang/Class")                          \
   template(java_lang_String,                          "java/lang/String")                         \
+  template(java_lang_StringValue,                     "java/lang/StringValue")                    \
+  template(java_lang_StringCache,                     "java/lang/StringValue$StringCache")        \
   template(java_lang_Thread,                          "java/lang/Thread")                         \
   template(java_lang_ThreadGroup,                     "java/lang/ThreadGroup")                    \
   template(java_lang_Cloneable,                       "java/lang/Cloneable")                      \
@@ -285,6 +287,8 @@
   template(frontCacheEnabled_name,                    "frontCacheEnabled")                        \
   template(stringCacheEnabled_name,                   "stringCacheEnabled")                       \
   template(bitCount_name,                             "bitCount")                                 \
+  template(profile_name,                              "profile")                                  \
+  template(equals_name,                               "equals")                                   \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -576,7 +580,6 @@
    do_signature(copyOfRange_signature,        "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;")            \
                                                                                                                         \
   do_intrinsic(_equalsC,                  java_util_Arrays,       equals_name,    equalsC_signature,             F_S)   \
-   do_name(     equals_name,                                     "equals")                                              \
    do_signature(equalsC_signature,                               "([C[C)Z")                                             \
                                                                                                                         \
   do_intrinsic(_invoke,                   java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
@@ -586,6 +589,7 @@
    do_name(     compareTo_name,                                  "compareTo")                                           \
   do_intrinsic(_indexOf,                  java_lang_String,       indexOf_name, string_int_signature,            F_R)   \
    do_name(     indexOf_name,                                    "indexOf")                                             \
+  do_intrinsic(_equals,                   java_lang_String,       equals_name, object_boolean_signature,         F_R)   \
                                                                                                                         \
   do_class(java_nio_Buffer,               "java/nio/Buffer")                                                            \
   do_intrinsic(_checkIndex,               java_nio_Buffer,        checkIndex_name, int_int_signature,            F_R)   \
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -3847,7 +3847,7 @@
   MutexLockerEx ml(ovflw_stk->par_lock(),
                    Mutex::_no_safepoint_check_flag);
   // Grab up to 1/4 the size of the work queue
-  size_t num = MIN2((size_t)work_q->max_elems()/4,
+  size_t num = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
                     (size_t)ParGCDesiredObjsFromOverflowList);
   num = MIN2(num, ovflw_stk->length());
   for (int i = (int) num; i > 0; i--) {
@@ -5204,13 +5204,12 @@
   NOT_PRODUCT(int num_steals = 0;)
   oop obj_to_scan;
   CMSBitMap* bm = &(_collector->_markBitMap);
-  size_t num_from_overflow_list =
-           MIN2((size_t)work_q->max_elems()/4,
-                (size_t)ParGCDesiredObjsFromOverflowList);
 
   while (true) {
     // Completely finish any left over work from (an) earlier round(s)
     cl->trim_queue(0);
+    size_t num_from_overflow_list = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
+                                         (size_t)ParGCDesiredObjsFromOverflowList);
     // Now check if there's any work in the overflow list
     if (_collector->par_take_from_overflow_list(num_from_overflow_list,
                                                 work_q)) {
@@ -5622,13 +5621,12 @@
   OopTaskQueue* work_q = work_queue(i);
   NOT_PRODUCT(int num_steals = 0;)
   oop obj_to_scan;
-  size_t num_from_overflow_list =
-           MIN2((size_t)work_q->max_elems()/4,
-                (size_t)ParGCDesiredObjsFromOverflowList);
 
   while (true) {
     // Completely finish any left over work from (an) earlier round(s)
     drain->trim_queue(0);
+    size_t num_from_overflow_list = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
+                                         (size_t)ParGCDesiredObjsFromOverflowList);
     // Now check if there's any work in the overflow list
     if (_collector->par_take_from_overflow_list(num_from_overflow_list,
                                                 work_q)) {
@@ -9021,7 +9019,7 @@
 // Transfer some number of overflown objects to usual marking
 // stack. Return true if some objects were transferred.
 bool MarkRefsIntoAndScanClosure::take_from_overflow_list() {
-  size_t num = MIN2((size_t)_mark_stack->capacity()/4,
+  size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4,
                     (size_t)ParGCDesiredObjsFromOverflowList);
 
   bool res = _collector->take_from_overflow_list(num, _mark_stack);
--- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -277,8 +277,6 @@
     gclog_or_tty->print("H: ");
   if (hr->in_collection_set())
     gclog_or_tty->print("CS: ");
-  if (hr->popular())
-    gclog_or_tty->print("pop: ");
   gclog_or_tty->print_cr("Region " PTR_FORMAT " (%s%s) "
                          "[" PTR_FORMAT ", " PTR_FORMAT"] "
                          "Used: " SIZE_FORMAT "K, garbage: " SIZE_FORMAT "K.",
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -42,21 +42,6 @@
 
 // Local to this file.
 
-// Finds the first HeapRegion.
-// No longer used, but might be handy someday.
-
-class FindFirstRegionClosure: public HeapRegionClosure {
-  HeapRegion* _a_region;
-public:
-  FindFirstRegionClosure() : _a_region(NULL) {}
-  bool doHeapRegion(HeapRegion* r) {
-    _a_region = r;
-    return true;
-  }
-  HeapRegion* result() { return _a_region; }
-};
-
-
 class RefineCardTableEntryClosure: public CardTableEntryClosure {
   SuspendibleThreadSet* _sts;
   G1RemSet* _g1rs;
@@ -1207,13 +1192,12 @@
                                                    bool par) {
   assert(!hr->continuesHumongous(), "should have filtered these out");
   size_t res = 0;
-  if (!hr->popular() && hr->used() > 0 && hr->garbage_bytes() == hr->used()) {
-    if (!hr->is_young()) {
-      if (G1PolicyVerbose > 0)
-        gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)"
-                               " during cleanup", hr, hr->used());
-      free_region_work(hr, pre_used, cleared_h, freed_regions, list, par);
-    }
+  if (hr->used() > 0 && hr->garbage_bytes() == hr->used() &&
+      !hr->is_young()) {
+    if (G1PolicyVerbose > 0)
+      gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)"
+                                                                               " during cleanup", hr, hr->used());
+    free_region_work(hr, pre_used, cleared_h, freed_regions, list, par);
   }
 }
 
@@ -1342,10 +1326,6 @@
   _refine_cte_cl(NULL),
   _free_region_list(NULL), _free_region_list_size(0),
   _free_regions(0),
-  _popular_object_boundary(NULL),
-  _cur_pop_hr_index(0),
-  _popular_regions_to_be_evacuated(NULL),
-  _pop_obj_rc_at_copy(),
   _full_collection(false),
   _unclean_region_list(),
   _unclean_regions_coming(false),
@@ -1520,26 +1500,11 @@
     _czft = new ConcurrentZFThread();
   }
 
-
-
-  // Allocate the popular regions; take them off free lists.
-  size_t pop_byte_size = G1NumPopularRegions * HeapRegion::GrainBytes;
-  expand(pop_byte_size);
-  _popular_object_boundary =
-    _g1_reserved.start() + (G1NumPopularRegions * HeapRegion::GrainWords);
-  for (int i = 0; i < G1NumPopularRegions; i++) {
-    HeapRegion* hr = newAllocRegion(HeapRegion::GrainWords);
-    //    assert(hr != NULL && hr->bottom() < _popular_object_boundary,
-    //     "Should be enough, and all should be below boundary.");
-    hr->set_popular(true);
-  }
-  assert(_cur_pop_hr_index == 0, "Start allocating at the first region.");
-
   // Initialize the from_card cache structure of HeapRegionRemSet.
   HeapRegionRemSet::init_heap(max_regions());
 
-  // Now expand into the rest of the initial heap size.
-  expand(init_byte_size - pop_byte_size);
+  // Now expand into the initial heap size.
+  expand(init_byte_size);
 
   // Perform any initialization actions delegated to the policy.
   g1_policy()->init();
@@ -1654,8 +1619,7 @@
 class SumUsedRegionsClosure: public HeapRegionClosure {
   size_t _num;
 public:
-  // _num is set to 1 to account for the popular region
-  SumUsedRegionsClosure() : _num(G1NumPopularRegions) {}
+  SumUsedRegionsClosure() : _num(0) {}
   bool doHeapRegion(HeapRegion* r) {
     if (r->continuesHumongous() || r->used() > 0 || r->is_gc_alloc_region()) {
       _num += 1;
@@ -1758,14 +1722,20 @@
   }
 };
 
-void G1CollectedHeap::oop_iterate(OopClosure* cl) {
+void G1CollectedHeap::oop_iterate(OopClosure* cl, bool do_perm) {
   IterateOopClosureRegionClosure blk(_g1_committed, cl);
   _hrs->iterate(&blk);
+  if (do_perm) {
+    perm_gen()->oop_iterate(cl);
+  }
 }
 
-void G1CollectedHeap::oop_iterate(MemRegion mr, OopClosure* cl) {
+void G1CollectedHeap::oop_iterate(MemRegion mr, OopClosure* cl, bool do_perm) {
   IterateOopClosureRegionClosure blk(mr, cl);
   _hrs->iterate(&blk);
+  if (do_perm) {
+    perm_gen()->oop_iterate(cl);
+  }
 }
 
 // Iterates an ObjectClosure over all objects within a HeapRegion.
@@ -1782,9 +1752,12 @@
   }
 };
 
-void G1CollectedHeap::object_iterate(ObjectClosure* cl) {
+void G1CollectedHeap::object_iterate(ObjectClosure* cl, bool do_perm) {
   IterateObjectClosureRegionClosure blk(cl);
   _hrs->iterate(&blk);
+  if (do_perm) {
+    perm_gen()->object_iterate(cl);
+  }
 }
 
 void G1CollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) {
@@ -2318,9 +2291,6 @@
   if (SummarizeG1ZFStats) {
     ConcurrentZFThread::print_summary_info();
   }
-  if (G1SummarizePopularity) {
-    print_popularity_summary_info();
-  }
   g1_policy()->print_yg_surv_rate_info();
 
   GCOverheadReporter::printGCOverhead();
@@ -2414,7 +2384,7 @@
     VerifyMarkedObjsClosure verifycl(this);
     //    MutexLockerEx x(getMarkBitMapLock(),
     //              Mutex::_no_safepoint_check_flag);
-    object_iterate(&verifycl);
+    object_iterate(&verifycl, false);
 }
 
 void G1CollectedHeap::do_sync_mark() {
@@ -2495,30 +2465,19 @@
 // </NEW PREDICTION>
 
 void
-G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) {
+G1CollectedHeap::do_collection_pause_at_safepoint() {
   char verbose_str[128];
   sprintf(verbose_str, "GC pause ");
-  if (popular_region != NULL)
-    strcat(verbose_str, "(popular)");
-  else if (g1_policy()->in_young_gc_mode()) {
+  if (g1_policy()->in_young_gc_mode()) {
     if (g1_policy()->full_young_gcs())
       strcat(verbose_str, "(young)");
     else
       strcat(verbose_str, "(partial)");
   }
-  bool reset_should_initiate_conc_mark = false;
-  if (popular_region != NULL && g1_policy()->should_initiate_conc_mark()) {
-    // we currently do not allow an initial mark phase to be piggy-backed
-    // on a popular pause
-    reset_should_initiate_conc_mark = true;
-    g1_policy()->unset_should_initiate_conc_mark();
-  }
   if (g1_policy()->should_initiate_conc_mark())
     strcat(verbose_str, " (initial-mark)");
 
-  GCCauseSetter x(this, (popular_region == NULL ?
-                         GCCause::_g1_inc_collection_pause :
-                         GCCause::_g1_pop_region_collection_pause));
+  GCCauseSetter x(this, GCCause::_g1_inc_collection_pause);
 
   // if PrintGCDetails is on, we'll print long statistics information
   // in the collector policy code, so let's not print this as the output
@@ -2609,7 +2568,7 @@
     save_marks();
 
     // We must do this before any possible evacuation that should propagate
-    // marks, including evacuation of popular objects in a popular pause.
+    // marks.
     if (mark_in_progress()) {
       double start_time_sec = os::elapsedTime();
 
@@ -2626,29 +2585,15 @@
 
     assert(regions_accounted_for(), "Region leakage.");
 
-    bool abandoned = false;
-
     if (mark_in_progress())
       concurrent_mark()->newCSet();
 
     // Now choose the CS.
-    if (popular_region == NULL) {
-      g1_policy()->choose_collection_set();
-    } else {
-      // We may be evacuating a single region (for popularity).
-      g1_policy()->record_popular_pause_preamble_start();
-      popularity_pause_preamble(popular_region);
-      g1_policy()->record_popular_pause_preamble_end();
-      abandoned = (g1_policy()->collection_set() == NULL);
-      // Now we allow more regions to be added (we have to collect
-      // all popular regions).
-      if (!abandoned) {
-        g1_policy()->choose_collection_set(popular_region);
-      }
-    }
+    g1_policy()->choose_collection_set();
+
     // We may abandon a pause if we find no region that will fit in the MMU
     // pause.
-    abandoned = (g1_policy()->collection_set() == NULL);
+    bool abandoned = (g1_policy()->collection_set() == NULL);
 
     // Nothing to do if we were unable to choose a collection set.
     if (!abandoned) {
@@ -2673,12 +2618,6 @@
       _in_cset_fast_test = NULL;
       _in_cset_fast_test_base = NULL;
 
-      if (popular_region != NULL) {
-        // We have to wait until now, because we don't want the region to
-        // be rescheduled for pop-evac during RS update.
-        popular_region->set_popular_pending(false);
-      }
-
       release_gc_alloc_regions(false /* totally */);
 
       cleanup_surviving_young_words();
@@ -2724,8 +2663,7 @@
     double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
     g1_policy()->record_pause_time_ms(pause_time_ms);
     GCOverheadReporter::recordSTWEnd(end_time_sec);
-    g1_policy()->record_collection_pause_end(popular_region != NULL,
-                                             abandoned);
+    g1_policy()->record_collection_pause_end(abandoned);
 
     assert(regions_accounted_for(), "Region leakage.");
 
@@ -2759,9 +2697,6 @@
 
   assert(verify_region_lists(), "Bad region lists.");
 
-  if (reset_should_initiate_conc_mark)
-    g1_policy()->set_should_initiate_conc_mark();
-
   if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {
     gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
     print_tracing_info();
@@ -4707,7 +4642,6 @@
                                   size_t& freed_regions,
                                   UncleanRegionList* list,
                                   bool par) {
-  assert(!hr->popular(), "should not free popular regions");
   pre_used += hr->used();
   if (hr->isHumongous()) {
     assert(hr->startsHumongous(),
@@ -4791,12 +4725,6 @@
 
 
 void G1CollectedHeap::do_collection_pause_if_appropriate(size_t word_size) {
-  // First do any popular regions.
-  HeapRegion* hr;
-  while ((hr = popular_region_to_evac()) != NULL) {
-    evac_popular_region(hr);
-  }
-  // Now do heuristic pauses.
   if (g1_policy()->should_do_collection_pause(word_size)) {
     do_collection_pause();
   }
@@ -5192,7 +5120,7 @@
 public:
   RegionCounter() : _n(0) {}
   bool doHeapRegion(HeapRegion* r) {
-    if (r->is_empty() && !r->popular()) {
+    if (r->is_empty()) {
       assert(!r->isHumongous(), "H regions should not be empty.");
       _n++;
     }
@@ -5336,14 +5264,8 @@
       r->set_zero_fill_allocated();
     } else {
       assert(r->is_empty(), "tautology");
-      if (r->popular()) {
-        if (r->zero_fill_state() != HeapRegion::Allocated) {
-          r->ensure_zero_filled_locked();
-          r->set_zero_fill_allocated();
-        }
-      } else {
-        _n++;
-        switch (r->zero_fill_state()) {
+      _n++;
+      switch (r->zero_fill_state()) {
         case HeapRegion::NotZeroFilled:
         case HeapRegion::ZeroFilling:
           _g1->put_region_on_unclean_list_locked(r);
@@ -5354,7 +5276,6 @@
         case HeapRegion::ZeroFilled:
           _g1->put_free_region_on_list_locked(r);
           break;
-        }
       }
     }
     return false;
@@ -5402,376 +5323,6 @@
   heap_region_iterate(&rs);
 }
 
-class CountObjClosure: public ObjectClosure {
-  size_t _n;
-public:
-  CountObjClosure() : _n(0) {}
-  void do_object(oop obj) { _n++; }
-  size_t n() { return _n; }
-};
-
-size_t G1CollectedHeap::pop_object_used_objs() {
-  size_t sum_objs = 0;
-  for (int i = 0; i < G1NumPopularRegions; i++) {
-    CountObjClosure cl;
-    _hrs->at(i)->object_iterate(&cl);
-    sum_objs += cl.n();
-  }
-  return sum_objs;
-}
-
-size_t G1CollectedHeap::pop_object_used_bytes() {
-  size_t sum_bytes = 0;
-  for (int i = 0; i < G1NumPopularRegions; i++) {
-    sum_bytes += _hrs->at(i)->used();
-  }
-  return sum_bytes;
-}
-
-
-static int nq = 0;
-
-HeapWord* G1CollectedHeap::allocate_popular_object(size_t word_size) {
-  while (_cur_pop_hr_index < G1NumPopularRegions) {
-    HeapRegion* cur_pop_region = _hrs->at(_cur_pop_hr_index);
-    HeapWord* res = cur_pop_region->allocate(word_size);
-    if (res != NULL) {
-      // We account for popular objs directly in the used summary:
-      _summary_bytes_used += (word_size * HeapWordSize);
-      return res;
-    }
-    // Otherwise, try the next region (first making sure that we remember
-    // the last "top" value as the "next_top_at_mark_start", so that
-    // objects made popular during markings aren't automatically considered
-    // live).
-    cur_pop_region->note_end_of_copying();
-    // Otherwise, try the next region.
-    _cur_pop_hr_index++;
-  }
-  // XXX: For now !!!
-  vm_exit_out_of_memory(word_size,
-                        "Not enough pop obj space (To Be Fixed)");
-  return NULL;
-}
-
-class HeapRegionList: public CHeapObj {
-  public:
-  HeapRegion* hr;
-  HeapRegionList* next;
-};
-
-void G1CollectedHeap::schedule_popular_region_evac(HeapRegion* r) {
-  // This might happen during parallel GC, so protect by this lock.
-  MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
-  // We don't schedule regions whose evacuations are already pending, or
-  // are already being evacuated.
-  if (!r->popular_pending() && !r->in_collection_set()) {
-    r->set_popular_pending(true);
-    if (G1TracePopularity) {
-      gclog_or_tty->print_cr("Scheduling region "PTR_FORMAT" "
-                             "["PTR_FORMAT", "PTR_FORMAT") for pop-object evacuation.",
-                             r, r->bottom(), r->end());
-    }
-    HeapRegionList* hrl = new HeapRegionList;
-    hrl->hr = r;
-    hrl->next = _popular_regions_to_be_evacuated;
-    _popular_regions_to_be_evacuated = hrl;
-  }
-}
-
-HeapRegion* G1CollectedHeap::popular_region_to_evac() {
-  MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
-  HeapRegion* res = NULL;
-  while (_popular_regions_to_be_evacuated != NULL && res == NULL) {
-    HeapRegionList* hrl = _popular_regions_to_be_evacuated;
-    _popular_regions_to_be_evacuated = hrl->next;
-    res = hrl->hr;
-    // The G1RSPopLimit may have increased, so recheck here...
-    if (res->rem_set()->occupied() < (size_t) G1RSPopLimit) {
-      // Hah: don't need to schedule.
-      if (G1TracePopularity) {
-        gclog_or_tty->print_cr("Unscheduling region "PTR_FORMAT" "
-                               "["PTR_FORMAT", "PTR_FORMAT") "
-                               "for pop-object evacuation (size %d < limit %d)",
-                               res, res->bottom(), res->end(),
-                               res->rem_set()->occupied(), G1RSPopLimit);
-      }
-      res->set_popular_pending(false);
-      res = NULL;
-    }
-    // We do not reset res->popular() here; if we did so, it would allow
-    // the region to be "rescheduled" for popularity evacuation.  Instead,
-    // this is done in the collection pause, with the world stopped.
-    // So the invariant is that the regions in the list have the popularity
-    // boolean set, but having the boolean set does not imply membership
-    // on the list (though there can at most one such pop-pending region
-    // not on the list at any time).
-    delete hrl;
-  }
-  return res;
-}
-
-void G1CollectedHeap::evac_popular_region(HeapRegion* hr) {
-  while (true) {
-    // Don't want to do a GC pause while cleanup is being completed!
-    wait_for_cleanup_complete();
-
-    // Read the GC count while holding the Heap_lock
-    int gc_count_before = SharedHeap::heap()->total_collections();
-    g1_policy()->record_stop_world_start();
-
-    {
-      MutexUnlocker mu(Heap_lock);  // give up heap lock, execute gets it back
-      VM_G1PopRegionCollectionPause op(gc_count_before, hr);
-      VMThread::execute(&op);
-
-      // If the prolog succeeded, we didn't do a GC for this.
-      if (op.prologue_succeeded()) break;
-    }
-    // Otherwise we didn't.  We should recheck the size, though, since
-    // the limit may have increased...
-    if (hr->rem_set()->occupied() < (size_t) G1RSPopLimit) {
-      hr->set_popular_pending(false);
-      break;
-    }
-  }
-}
-
-void G1CollectedHeap::atomic_inc_obj_rc(oop obj) {
-  Atomic::inc(obj_rc_addr(obj));
-}
-
-class CountRCClosure: public OopsInHeapRegionClosure {
-  G1CollectedHeap* _g1h;
-  bool _parallel;
-public:
-  CountRCClosure(G1CollectedHeap* g1h) :
-    _g1h(g1h), _parallel(ParallelGCThreads > 0)
-  {}
-  void do_oop(narrowOop* p) {
-    guarantee(false, "NYI");
-  }
-  void do_oop(oop* p) {
-    oop obj = *p;
-    assert(obj != NULL, "Precondition.");
-    if (_parallel) {
-      // We go sticky at the limit to avoid excess contention.
-      // If we want to track the actual RC's further, we'll need to keep a
-      // per-thread hash table or something for the popular objects.
-      if (_g1h->obj_rc(obj) < G1ObjPopLimit) {
-        _g1h->atomic_inc_obj_rc(obj);
-      }
-    } else {
-      _g1h->inc_obj_rc(obj);
-    }
-  }
-};
-
-class EvacPopObjClosure: public ObjectClosure {
-  G1CollectedHeap* _g1h;
-  size_t _pop_objs;
-  size_t _max_rc;
-public:
-  EvacPopObjClosure(G1CollectedHeap* g1h) :
-    _g1h(g1h), _pop_objs(0), _max_rc(0) {}
-
-  void do_object(oop obj) {
-    size_t rc = _g1h->obj_rc(obj);
-    _max_rc = MAX2(rc, _max_rc);
-    if (rc >= (size_t) G1ObjPopLimit) {
-      _g1h->_pop_obj_rc_at_copy.add((double)rc);
-      size_t word_sz = obj->size();
-      HeapWord* new_pop_loc = _g1h->allocate_popular_object(word_sz);
-      oop new_pop_obj = (oop)new_pop_loc;
-      Copy::aligned_disjoint_words((HeapWord*)obj, new_pop_loc, word_sz);
-      obj->forward_to(new_pop_obj);
-      G1ScanAndBalanceClosure scan_and_balance(_g1h);
-      new_pop_obj->oop_iterate_backwards(&scan_and_balance);
-      // preserve "next" mark bit if marking is in progress.
-      if (_g1h->mark_in_progress() && !_g1h->is_obj_ill(obj)) {
-        _g1h->concurrent_mark()->markAndGrayObjectIfNecessary(new_pop_obj);
-      }
-
-      if (G1TracePopularity) {
-        gclog_or_tty->print_cr("Found obj " PTR_FORMAT " of word size " SIZE_FORMAT
-                               " pop (%d), move to " PTR_FORMAT,
-                               (void*) obj, word_sz,
-                               _g1h->obj_rc(obj), (void*) new_pop_obj);
-      }
-      _pop_objs++;
-    }
-  }
-  size_t pop_objs() { return _pop_objs; }
-  size_t max_rc() { return _max_rc; }
-};
-
-class G1ParCountRCTask : public AbstractGangTask {
-  G1CollectedHeap* _g1h;
-  BitMap _bm;
-
-  size_t getNCards() {
-    return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1)
-      / G1BlockOffsetSharedArray::N_bytes;
-  }
-  CountRCClosure _count_rc_closure;
-public:
-  G1ParCountRCTask(G1CollectedHeap* g1h) :
-    AbstractGangTask("G1 Par RC Count task"),
-    _g1h(g1h), _bm(getNCards()), _count_rc_closure(g1h)
-  {}
-
-  void work(int i) {
-    ResourceMark rm;
-    HandleMark   hm;
-    _g1h->g1_rem_set()->oops_into_collection_set_do(&_count_rc_closure, i);
-  }
-};
-
-void G1CollectedHeap::popularity_pause_preamble(HeapRegion* popular_region) {
-  // We're evacuating a single region (for popularity).
-  if (G1TracePopularity) {
-    gclog_or_tty->print_cr("Doing pop region pause for ["PTR_FORMAT", "PTR_FORMAT")",
-                           popular_region->bottom(), popular_region->end());
-  }
-  g1_policy()->set_single_region_collection_set(popular_region);
-  size_t max_rc;
-  if (!compute_reference_counts_and_evac_popular(popular_region,
-                                                 &max_rc)) {
-    // We didn't evacuate any popular objects.
-    // We increase the RS popularity limit, to prevent this from
-    // happening in the future.
-    if (G1RSPopLimit < (1 << 30)) {
-      G1RSPopLimit *= 2;
-    }
-    // For now, interesting enough for a message:
-#if 1
-    gclog_or_tty->print_cr("In pop region pause for ["PTR_FORMAT", "PTR_FORMAT"), "
-                           "failed to find a pop object (max = %d).",
-                           popular_region->bottom(), popular_region->end(),
-                           max_rc);
-    gclog_or_tty->print_cr("Increased G1RSPopLimit to %d.", G1RSPopLimit);
-#endif // 0
-    // Also, we reset the collection set to NULL, to make the rest of
-    // the collection do nothing.
-    assert(popular_region->next_in_collection_set() == NULL,
-           "should be single-region.");
-    popular_region->set_in_collection_set(false);
-    popular_region->set_popular_pending(false);
-    g1_policy()->clear_collection_set();
-  }
-}
-
-bool G1CollectedHeap::
-compute_reference_counts_and_evac_popular(HeapRegion* popular_region,
-                                          size_t* max_rc) {
-  HeapWord* rc_region_bot;
-  HeapWord* rc_region_end;
-
-  // Set up the reference count region.
-  HeapRegion* rc_region = newAllocRegion(HeapRegion::GrainWords);
-  if (rc_region != NULL) {
-    rc_region_bot = rc_region->bottom();
-    rc_region_end = rc_region->end();
-  } else {
-    rc_region_bot = NEW_C_HEAP_ARRAY(HeapWord, HeapRegion::GrainWords);
-    if (rc_region_bot == NULL) {
-      vm_exit_out_of_memory(HeapRegion::GrainWords,
-                            "No space for RC region.");
-    }
-    rc_region_end = rc_region_bot + HeapRegion::GrainWords;
-  }
-
-  if (G1TracePopularity)
-    gclog_or_tty->print_cr("RC region is ["PTR_FORMAT", "PTR_FORMAT")",
-                           rc_region_bot, rc_region_end);
-  if (rc_region_bot > popular_region->bottom()) {
-    _rc_region_above = true;
-    _rc_region_diff =
-      pointer_delta(rc_region_bot, popular_region->bottom(), 1);
-  } else {
-    assert(rc_region_bot < popular_region->bottom(), "Can't be equal.");
-    _rc_region_above = false;
-    _rc_region_diff =
-      pointer_delta(popular_region->bottom(), rc_region_bot, 1);
-  }
-  g1_policy()->record_pop_compute_rc_start();
-  // Count external references.
-  g1_rem_set()->prepare_for_oops_into_collection_set_do();
-  if (ParallelGCThreads > 0) {
-
-    set_par_threads(workers()->total_workers());
-    G1ParCountRCTask par_count_rc_task(this);
-    workers()->run_task(&par_count_rc_task);
-    set_par_threads(0);
-
-  } else {
-    CountRCClosure count_rc_closure(this);
-    g1_rem_set()->oops_into_collection_set_do(&count_rc_closure, 0);
-  }
-  g1_rem_set()->cleanup_after_oops_into_collection_set_do();
-  g1_policy()->record_pop_compute_rc_end();
-
-  // Now evacuate popular objects.
-  g1_policy()->record_pop_evac_start();
-  EvacPopObjClosure evac_pop_obj_cl(this);
-  popular_region->object_iterate(&evac_pop_obj_cl);
-  *max_rc = evac_pop_obj_cl.max_rc();
-
-  // Make sure the last "top" value of the current popular region is copied
-  // as the "next_top_at_mark_start", so that objects made popular during
-  // markings aren't automatically considered live.
-  HeapRegion* cur_pop_region = _hrs->at(_cur_pop_hr_index);
-  cur_pop_region->note_end_of_copying();
-
-  if (rc_region != NULL) {
-    free_region(rc_region);
-  } else {
-    FREE_C_HEAP_ARRAY(HeapWord, rc_region_bot);
-  }
-  g1_policy()->record_pop_evac_end();
-
-  return evac_pop_obj_cl.pop_objs() > 0;
-}
-
-class CountPopObjInfoClosure: public HeapRegionClosure {
-  size_t _objs;
-  size_t _bytes;
-
-  class CountObjClosure: public ObjectClosure {
-    int _n;
-  public:
-    CountObjClosure() : _n(0) {}
-    void do_object(oop obj) { _n++; }
-    size_t n() { return _n; }
-  };
-
-public:
-  CountPopObjInfoClosure() : _objs(0), _bytes(0) {}
-  bool doHeapRegion(HeapRegion* r) {
-    _bytes += r->used();
-    CountObjClosure blk;
-    r->object_iterate(&blk);
-    _objs += blk.n();
-    return false;
-  }
-  size_t objs() { return _objs; }
-  size_t bytes() { return _bytes; }
-};
-
-
-void G1CollectedHeap::print_popularity_summary_info() const {
-  CountPopObjInfoClosure blk;
-  for (int i = 0; i <= _cur_pop_hr_index; i++) {
-    blk.doHeapRegion(_hrs->at(i));
-  }
-  gclog_or_tty->print_cr("\nPopular objects: %d objs, %d bytes.",
-                         blk.objs(), blk.bytes());
-  gclog_or_tty->print_cr("   RC at copy = [avg = %5.2f, max = %5.2f, sd = %5.2f].",
-                _pop_obj_rc_at_copy.avg(),
-                _pop_obj_rc_at_copy.maximum(),
-                _pop_obj_rc_at_copy.sd());
-}
-
 void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) {
   _refine_cte_cl->set_concurrent(concurrent);
 }
@@ -5845,7 +5396,6 @@
 }
 
 bool G1CollectedHeap::print_region_accounting_info() {
-  gclog_or_tty->print_cr("P regions: %d.", G1NumPopularRegions);
   gclog_or_tty->print_cr("Free regions: %d (count: %d count list %d) (clean: %d unclean: %d).",
                          free_regions(),
                          count_free_regions(), count_free_regions_list(),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,6 @@
 
 class HeapRegion;
 class HeapRegionSeq;
-class HeapRegionList;
 class PermanentGenerationSpec;
 class GenerationSpec;
 class OopsInHeapRegionClosure;
@@ -143,7 +142,6 @@
   friend class VM_GenCollectForPermanentAllocation;
   friend class VM_G1CollectFull;
   friend class VM_G1IncCollectionPause;
-  friend class VM_G1PopRegionCollectionPause;
   friend class VMStructs;
 
   // Closures used in implementation.
@@ -253,10 +251,6 @@
   // than the current allocation region.
   size_t _summary_bytes_used;
 
-  // Summary information about popular objects; method to print it.
-  NumberSeq _pop_obj_rc_at_copy;
-  void print_popularity_summary_info() const;
-
   // This is used for a quick test on whether a reference points into
   // the collection set or not. Basically, we have an array, with one
   // byte per region, and that byte denotes whether the corresponding
@@ -447,10 +441,8 @@
   virtual void do_collection_pause();
 
   // The guts of the incremental collection pause, executed by the vm
-  // thread.  If "popular_region" is non-NULL, this pause should evacuate
-  // this single region whose remembered set has gotten large, moving
-  // any popular objects to one of the popular regions.
-  virtual void do_collection_pause_at_safepoint(HeapRegion* popular_region);
+  // thread.
+  virtual void do_collection_pause_at_safepoint();
 
   // Actually do the work of evacuating the collection set.
   virtual void evacuate_collection_set();
@@ -625,67 +617,10 @@
 
   SubTasksDone* _process_strong_tasks;
 
-  // Allocate space to hold a popular object.  Result is guaranteed below
-  // "popular_object_boundary()".  Note: CURRENTLY halts the system if we
-  // run out of space to hold popular objects.
-  HeapWord* allocate_popular_object(size_t word_size);
-
-  // The boundary between popular and non-popular objects.
-  HeapWord* _popular_object_boundary;
-
-  HeapRegionList* _popular_regions_to_be_evacuated;
-
-  // Compute which objects in "single_region" are popular.  If any are,
-  // evacuate them to a popular region, leaving behind forwarding pointers,
-  // and select "popular_region" as the single collection set region.
-  // Otherwise, leave the collection set null.
-  void popularity_pause_preamble(HeapRegion* populer_region);
-
-  // Compute which objects in "single_region" are popular, and evacuate
-  // them to a popular region, leaving behind forwarding pointers.
-  // Returns "true" if at least one popular object is discovered and
-  // evacuated.  In any case, "*max_rc" is set to the maximum reference
-  // count of an object in the region.
-  bool compute_reference_counts_and_evac_popular(HeapRegion* populer_region,
-                                                 size_t* max_rc);
-  // Subroutines used in the above.
-  bool _rc_region_above;
-  size_t _rc_region_diff;
-  jint* obj_rc_addr(oop obj) {
-    uintptr_t obj_addr = (uintptr_t)obj;
-    if (_rc_region_above) {
-      jint* res = (jint*)(obj_addr + _rc_region_diff);
-      assert((uintptr_t)res > obj_addr, "RC region is above.");
-      return res;
-    } else {
-      jint* res = (jint*)(obj_addr - _rc_region_diff);
-      assert((uintptr_t)res < obj_addr, "RC region is below.");
-      return res;
-    }
-  }
-  jint obj_rc(oop obj) {
-    return *obj_rc_addr(obj);
-  }
-  void inc_obj_rc(oop obj) {
-    (*obj_rc_addr(obj))++;
-  }
-  void atomic_inc_obj_rc(oop obj);
-
-
-  // Number of popular objects and bytes (latter is cheaper!).
-  size_t pop_object_used_objs();
-  size_t pop_object_used_bytes();
-
-  // Index of the popular region in which allocation is currently being
-  // done.
-  int _cur_pop_hr_index;
-
   // List of regions which require zero filling.
   UncleanRegionList _unclean_region_list;
   bool _unclean_regions_coming;
 
-  bool check_age_cohort_well_formed_work(int a, HeapRegion* hr);
-
 public:
   void set_refine_cte_cl_concurrency(bool concurrent);
 
@@ -930,14 +865,25 @@
 
   // Iterate over all the ref-containing fields of all objects, calling
   // "cl.do_oop" on each.
-  virtual void oop_iterate(OopClosure* cl);
+  virtual void oop_iterate(OopClosure* cl) {
+    oop_iterate(cl, true);
+  }
+  void oop_iterate(OopClosure* cl, bool do_perm);
 
   // Same as above, restricted to a memory region.
-  virtual void oop_iterate(MemRegion mr, OopClosure* cl);
+  virtual void oop_iterate(MemRegion mr, OopClosure* cl) {
+    oop_iterate(mr, cl, true);
+  }
+  void oop_iterate(MemRegion mr, OopClosure* cl, bool do_perm);
 
   // Iterate over all objects, calling "cl.do_object" on each.
-  virtual void object_iterate(ObjectClosure* cl);
-  virtual void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); }
+  virtual void object_iterate(ObjectClosure* cl) {
+    object_iterate(cl, true);
+  }
+  virtual void safe_object_iterate(ObjectClosure* cl) {
+    object_iterate(cl, true);
+  }
+  void object_iterate(ObjectClosure* cl, bool do_perm);
 
   // Iterate over all objects allocated since the last collection, calling
   // "cl.do_object" on each.  The heap must have been initialized properly
@@ -1066,21 +1012,6 @@
   // words.
   virtual size_t large_typearray_limit();
 
-  // All popular objects are guaranteed to have addresses below this
-  // boundary.
-  HeapWord* popular_object_boundary() {
-    return _popular_object_boundary;
-  }
-
-  // Declare the region as one that should be evacuated because its
-  // remembered set is too large.
-  void schedule_popular_region_evac(HeapRegion* r);
-  // If there is a popular region to evacuate it, remove it from the list
-  // and return it.
-  HeapRegion* popular_region_to_evac();
-  // Evacuate the given popular region.
-  void evac_popular_region(HeapRegion* r);
-
   // Returns "true" iff the given word_size is "very large".
   static bool isHumongous(size_t word_size) {
     return word_size >= VeryLargeInWords;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -91,10 +91,8 @@
 
   _all_mod_union_times_ms(new NumberSeq()),
 
-  _non_pop_summary(new NonPopSummary()),
-  _pop_summary(new PopSummary()),
-  _non_pop_abandoned_summary(new NonPopAbandonedSummary()),
-  _pop_abandoned_summary(new PopAbandonedSummary()),
+  _summary(new Summary()),
+  _abandoned_summary(new AbandonedSummary()),
 
   _cur_clear_ct_time_ms(0.0),
 
@@ -109,9 +107,6 @@
   _cur_aux_times_ms(new double[_aux_num]),
   _cur_aux_times_set(new bool[_aux_num]),
 
-  _pop_compute_rc_start(0.0),
-  _pop_evac_start(0.0),
-
   _concurrent_mark_init_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
   _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
   _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
@@ -224,16 +219,6 @@
 
   _par_last_termination_times_ms = new double[_parallel_gc_threads];
 
-  // we store the data from the first pass during popularity pauses
-  _pop_par_last_update_rs_start_times_ms = new double[_parallel_gc_threads];
-  _pop_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
-  _pop_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
-
-  _pop_par_last_scan_rs_start_times_ms = new double[_parallel_gc_threads];
-  _pop_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
-
-  _pop_par_last_closure_app_times_ms = new double[_parallel_gc_threads];
-
   // start conservatively
   _expensive_region_limit_ms = 0.5 * (double) G1MaxPauseTimeMS;
 
@@ -1047,23 +1032,6 @@
   calculate_young_list_target_config();
  }
 
-void G1CollectorPolicy::record_pop_compute_rc_start() {
-  _pop_compute_rc_start = os::elapsedTime();
-}
-void G1CollectorPolicy::record_pop_compute_rc_end() {
-  double ms = (os::elapsedTime() - _pop_compute_rc_start)*1000.0;
-  _cur_popular_compute_rc_time_ms = ms;
-  _pop_compute_rc_start = 0.0;
-}
-void G1CollectorPolicy::record_pop_evac_start() {
-  _pop_evac_start = os::elapsedTime();
-}
-void G1CollectorPolicy::record_pop_evac_end() {
-  double ms = (os::elapsedTime() - _pop_evac_start)*1000.0;
-  _cur_popular_evac_time_ms = ms;
-  _pop_evac_start = 0.0;
-}
-
 void G1CollectorPolicy::record_before_bytes(size_t bytes) {
   _bytes_in_to_space_before_gc += bytes;
 }
@@ -1120,13 +1088,6 @@
     _par_last_scan_new_refs_times_ms[i] = -666.0;
     _par_last_obj_copy_times_ms[i] = -666.0;
     _par_last_termination_times_ms[i] = -666.0;
-
-    _pop_par_last_update_rs_start_times_ms[i] = -666.0;
-    _pop_par_last_update_rs_times_ms[i] = -666.0;
-    _pop_par_last_update_rs_processed_buffers[i] = -666.0;
-    _pop_par_last_scan_rs_start_times_ms[i] = -666.0;
-    _pop_par_last_scan_rs_times_ms[i] = -666.0;
-    _pop_par_last_closure_app_times_ms[i] = -666.0;
   }
 #endif
 
@@ -1185,25 +1146,6 @@
   guarantee( false, "we should never reach here" );
 }
 
-void G1CollectorPolicy::record_popular_pause_preamble_start() {
-  _cur_popular_preamble_start_ms = os::elapsedTime() * 1000.0;
-}
-
-void G1CollectorPolicy::record_popular_pause_preamble_end() {
-  _cur_popular_preamble_time_ms =
-    (os::elapsedTime() * 1000.0) - _cur_popular_preamble_start_ms;
-
-  // copy the recorded statistics of the first pass to temporary arrays
-  for (int i = 0; i < _parallel_gc_threads; ++i) {
-    _pop_par_last_update_rs_start_times_ms[i] = _par_last_update_rs_start_times_ms[i];
-    _pop_par_last_update_rs_times_ms[i] = _par_last_update_rs_times_ms[i];
-    _pop_par_last_update_rs_processed_buffers[i] = _par_last_update_rs_processed_buffers[i];
-    _pop_par_last_scan_rs_start_times_ms[i] = _par_last_scan_rs_start_times_ms[i];
-    _pop_par_last_scan_rs_times_ms[i] = _par_last_scan_rs_times_ms[i];
-    _pop_par_last_closure_app_times_ms[i] = _par_last_obj_copy_times_ms[i];
-  }
-}
-
 void G1CollectorPolicy::record_mark_closure_time(double mark_closure_time_ms) {
   _mark_closure_time_ms = mark_closure_time_ms;
 }
@@ -1465,8 +1407,7 @@
 // Anything below that is considered to be zero
 #define MIN_TIMER_GRANULARITY 0.0000001
 
-void G1CollectorPolicy::record_collection_pause_end(bool popular,
-                                                    bool abandoned) {
+void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
   double end_time_sec = os::elapsedTime();
   double elapsed_ms = _last_pause_time_ms;
   bool parallel = ParallelGCThreads > 0;
@@ -1587,42 +1528,10 @@
   }
 
   PauseSummary* summary;
-  if (!abandoned && !popular)
-    summary = _non_pop_summary;
-  else if (!abandoned && popular)
-    summary = _pop_summary;
-  else if (abandoned && !popular)
-    summary = _non_pop_abandoned_summary;
-  else if (abandoned && popular)
-    summary = _pop_abandoned_summary;
-  else
-    guarantee(false, "should not get here!");
-
-  double pop_update_rs_time;
-  double pop_update_rs_processed_buffers;
-  double pop_scan_rs_time;
-  double pop_closure_app_time;
-  double pop_other_time;
-
-  if (popular) {
-    PopPreambleSummary* preamble_summary = summary->pop_preamble_summary();
-    guarantee(preamble_summary != NULL, "should not be null!");
-
-    pop_update_rs_time = avg_value(_pop_par_last_update_rs_times_ms);
-    pop_update_rs_processed_buffers =
-      sum_of_values(_pop_par_last_update_rs_processed_buffers);
-    pop_scan_rs_time = avg_value(_pop_par_last_scan_rs_times_ms);
-    pop_closure_app_time = avg_value(_pop_par_last_closure_app_times_ms);
-    pop_other_time = _cur_popular_preamble_time_ms -
-      (pop_update_rs_time + pop_scan_rs_time + pop_closure_app_time +
-       _cur_popular_evac_time_ms);
-
-    preamble_summary->record_pop_preamble_time_ms(_cur_popular_preamble_time_ms);
-    preamble_summary->record_pop_update_rs_time_ms(pop_update_rs_time);
-    preamble_summary->record_pop_scan_rs_time_ms(pop_scan_rs_time);
-    preamble_summary->record_pop_closure_app_time_ms(pop_closure_app_time);
-    preamble_summary->record_pop_evacuation_time_ms(_cur_popular_evac_time_ms);
-    preamble_summary->record_pop_other_time_ms(pop_other_time);
+  if (abandoned) {
+    summary = _abandoned_summary;
+  } else {
+    summary = _summary;
   }
 
   double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
@@ -1694,8 +1603,6 @@
   }
 
   double other_time_ms = elapsed_ms;
-  if (popular)
-    other_time_ms -= _cur_popular_preamble_time_ms;
 
   if (!abandoned) {
     if (_satb_drain_time_set)
@@ -1712,41 +1619,24 @@
 
   if (PrintGCDetails) {
     gclog_or_tty->print_cr("%s%s, %1.8lf secs]",
-                           (popular && !abandoned) ? " (popular)" :
-                           (!popular && abandoned) ? " (abandoned)" :
-                           (popular && abandoned) ? " (popular/abandoned)" : "",
+                           abandoned ? " (abandoned)" : "",
                            (last_pause_included_initial_mark) ? " (initial-mark)" : "",
                            elapsed_ms / 1000.0);
 
     if (!abandoned) {
-      if (_satb_drain_time_set)
+      if (_satb_drain_time_set) {
         print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
-      if (_last_satb_drain_processed_buffers >= 0)
+      }
+      if (_last_satb_drain_processed_buffers >= 0) {
         print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
-    }
-    if (popular)
-      print_stats(1, "Popularity Preamble", _cur_popular_preamble_time_ms);
-    if (parallel) {
-      if (popular) {
-        print_par_stats(2, "Update RS (Start)", _pop_par_last_update_rs_start_times_ms, false);
-        print_par_stats(2, "Update RS", _pop_par_last_update_rs_times_ms);
+      }
+      if (parallel) {
+        print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
+        print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
+        print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
         if (G1RSBarrierUseQueue)
           print_par_buffers(3, "Processed Buffers",
-                            _pop_par_last_update_rs_processed_buffers, true);
-        print_par_stats(2, "Scan RS", _pop_par_last_scan_rs_times_ms);
-        print_par_stats(2, "Closure app", _pop_par_last_closure_app_times_ms);
-        print_stats(2, "Evacuation", _cur_popular_evac_time_ms);
-        print_stats(2, "Other", pop_other_time);
-      }
-      if (!abandoned) {
-        print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
-        if (!popular) {
-          print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
-          print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
-          if (G1RSBarrierUseQueue)
-            print_par_buffers(3, "Processed Buffers",
-                              _par_last_update_rs_processed_buffers, true);
-        }
+                            _par_last_update_rs_processed_buffers, true);
         print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
         print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
         print_par_stats(2, "Scan-Only Scanning", _par_last_scan_only_times_ms);
@@ -1757,25 +1647,11 @@
         print_par_stats(2, "Termination", _par_last_termination_times_ms);
         print_stats(2, "Other", parallel_other_time);
         print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
-      }
-    } else {
-      if (popular) {
-        print_stats(2, "Update RS", pop_update_rs_time);
+      } else {
+        print_stats(1, "Update RS", update_rs_time);
         if (G1RSBarrierUseQueue)
-          print_stats(3, "Processed Buffers",
-                      (int)pop_update_rs_processed_buffers);
-        print_stats(2, "Scan RS", pop_scan_rs_time);
-        print_stats(2, "Closure App", pop_closure_app_time);
-        print_stats(2, "Evacuation", _cur_popular_evac_time_ms);
-        print_stats(2, "Other", pop_other_time);
-      }
-      if (!abandoned) {
-        if (!popular) {
-          print_stats(1, "Update RS", update_rs_time);
-          if (G1RSBarrierUseQueue)
-            print_stats(2, "Processed Buffers",
-                        (int)update_rs_processed_buffers);
-        }
+          print_stats(2, "Processed Buffers",
+                      (int)update_rs_processed_buffers);
         print_stats(1, "Ext Root Scanning", ext_root_scan_time);
         print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
         print_stats(1, "Scan-Only Scanning", scan_only_time);
@@ -1855,7 +1731,7 @@
 
   // <NEW PREDICTION>
 
-  if (!popular && update_stats) {
+  if (update_stats) {
     double pause_time_ms = elapsed_ms;
 
     size_t diff = 0;
@@ -2454,36 +2330,8 @@
 void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
   bool parallel = ParallelGCThreads > 0;
   MainBodySummary*    body_summary = summary->main_body_summary();
-  PopPreambleSummary* preamble_summary = summary->pop_preamble_summary();
-
   if (summary->get_total_seq()->num() > 0) {
-    print_summary_sd(0,
-                     (preamble_summary == NULL) ? "Non-Popular Pauses" :
-                     "Popular Pauses",
-                     summary->get_total_seq());
-    if (preamble_summary != NULL) {
-      print_summary(1, "Popularity Preamble",
-                    preamble_summary->get_pop_preamble_seq());
-      print_summary(2, "Update RS", preamble_summary->get_pop_update_rs_seq());
-      print_summary(2, "Scan RS", preamble_summary->get_pop_scan_rs_seq());
-      print_summary(2, "Closure App",
-                    preamble_summary->get_pop_closure_app_seq());
-      print_summary(2, "Evacuation",
-                    preamble_summary->get_pop_evacuation_seq());
-      print_summary(2, "Other", preamble_summary->get_pop_other_seq());
-      {
-        NumberSeq* other_parts[] = {
-          preamble_summary->get_pop_update_rs_seq(),
-          preamble_summary->get_pop_scan_rs_seq(),
-          preamble_summary->get_pop_closure_app_seq(),
-          preamble_summary->get_pop_evacuation_seq()
-        };
-        NumberSeq calc_other_times_ms(preamble_summary->get_pop_preamble_seq(),
-                                      4, other_parts);
-        check_other_times(2, preamble_summary->get_pop_other_seq(),
-                          &calc_other_times_ms);
-      }
-    }
+    print_summary_sd(0, "Evacuation Pauses", summary->get_total_seq());
     if (body_summary != NULL) {
       print_summary(1, "SATB Drain", body_summary->get_satb_drain_seq());
       if (parallel) {
@@ -2537,19 +2385,15 @@
           // parallel
           NumberSeq* other_parts[] = {
             body_summary->get_satb_drain_seq(),
-            (preamble_summary == NULL) ? NULL :
-              preamble_summary->get_pop_preamble_seq(),
             body_summary->get_parallel_seq(),
             body_summary->get_clear_ct_seq()
           };
-          calc_other_times_ms = NumberSeq (summary->get_total_seq(),
-                                          4, other_parts);
+          calc_other_times_ms = NumberSeq(summary->get_total_seq(),
+                                          3, other_parts);
         } else {
           // serial
           NumberSeq* other_parts[] = {
             body_summary->get_satb_drain_seq(),
-            (preamble_summary == NULL) ? NULL :
-              preamble_summary->get_pop_preamble_seq(),
             body_summary->get_update_rs_seq(),
             body_summary->get_ext_root_scan_seq(),
             body_summary->get_mark_stack_scan_seq(),
@@ -2558,16 +2402,11 @@
             body_summary->get_obj_copy_seq()
           };
           calc_other_times_ms = NumberSeq(summary->get_total_seq(),
-                                          8, other_parts);
+                                          7, other_parts);
         }
       } else {
         // abandoned
-        NumberSeq* other_parts[] = {
-          (preamble_summary == NULL) ? NULL :
-            preamble_summary->get_pop_preamble_seq()
-        };
-        calc_other_times_ms = NumberSeq(summary->get_total_seq(),
-                                        1, other_parts);
+        calc_other_times_ms = NumberSeq();
       }
       check_other_times(1,  summary->get_other_seq(), &calc_other_times_ms);
     }
@@ -2579,18 +2418,12 @@
 }
 
 void
-G1CollectorPolicy::print_abandoned_summary(PauseSummary* non_pop_summary,
-                                           PauseSummary* pop_summary) const {
+G1CollectorPolicy::print_abandoned_summary(PauseSummary* summary) const {
   bool printed = false;
-  if (non_pop_summary->get_total_seq()->num() > 0) {
+  if (summary->get_total_seq()->num() > 0) {
     printed = true;
-    print_summary(non_pop_summary);
+    print_summary(summary);
   }
-  if (pop_summary->get_total_seq()->num() > 0) {
-    printed = true;
-    print_summary(pop_summary);
-  }
-
   if (!printed) {
     print_indent(0);
     gclog_or_tty->print_cr("none");
@@ -2608,15 +2441,11 @@
     gclog_or_tty->print_cr("   Partial Young GC Pauses: %8d", _partial_young_pause_num);
     gclog_or_tty->print_cr("");
 
-    gclog_or_tty->print_cr("NON-POPULAR PAUSES");
-    print_summary(_non_pop_summary);
-
-    gclog_or_tty->print_cr("POPULAR PAUSES");
-    print_summary(_pop_summary);
+    gclog_or_tty->print_cr("EVACUATION PAUSES");
+    print_summary(_summary);
 
     gclog_or_tty->print_cr("ABANDONED PAUSES");
-    print_abandoned_summary(_non_pop_abandoned_summary,
-                            _pop_abandoned_summary);
+    print_abandoned_summary(_abandoned_summary);
 
     gclog_or_tty->print_cr("MISC");
     print_summary_sd(0, "Stop World", _all_stop_world_times_ms);
@@ -2702,14 +2531,6 @@
   _conc_refine_enabled++;
 }
 
-void G1CollectorPolicy::set_single_region_collection_set(HeapRegion* hr) {
-  assert(collection_set() == NULL, "Must be no current CS.");
-  _collection_set_size = 0;
-  _collection_set_bytes_used_before = 0;
-  add_to_collection_set(hr);
-  count_CS_bytes_used();
-}
-
 bool
 G1CollectorPolicy::should_add_next_region_to_young_list() {
   assert(in_young_gc_mode(), "should be in young GC mode");
@@ -2787,15 +2608,6 @@
   }
 }
 
-
-void
-G1CollectorPolicy_BestRegionsFirst::
-set_single_region_collection_set(HeapRegion* hr) {
-  G1CollectorPolicy::set_single_region_collection_set(hr);
-  _collectionSetChooser->removeRegion(hr);
-}
-
-
 bool
 G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t
                                                                word_size) {
@@ -3061,19 +2873,13 @@
 
 void
 G1CollectorPolicy_BestRegionsFirst::
-choose_collection_set(HeapRegion* pop_region) {
+choose_collection_set() {
   double non_young_start_time_sec;
   start_recording_regions();
 
-  if (pop_region != NULL) {
-    _target_pause_time_ms = (double) G1MaxPauseTimeMS;
-  } else {
-    guarantee(_target_pause_time_ms > -1.0,
-              "_target_pause_time_ms should have been set!");
-  }
-
-  // pop region is either null (and so is CS), or else it *is* the CS.
-  assert(_collection_set == pop_region, "Precondition");
+  guarantee(_target_pause_time_ms > -1.0,
+            "_target_pause_time_ms should have been set!");
+  assert(_collection_set == NULL, "Precondition");
 
   double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
   double predicted_pause_time_ms = base_time_ms;
@@ -3100,15 +2906,13 @@
   size_t expansion_bytes =
     _g1->expansion_regions() * HeapRegion::GrainBytes;
 
-  if (pop_region == NULL) {
-    _collection_set_bytes_used_before = 0;
-    _collection_set_size = 0;
-  }
+  _collection_set_bytes_used_before = 0;
+  _collection_set_size = 0;
 
   // Adjust for expansion and slop.
   max_live_bytes = max_live_bytes + expansion_bytes;
 
-  assert(pop_region != NULL || _g1->regions_accounted_for(), "Region leakage!");
+  assert(_g1->regions_accounted_for(), "Region leakage!");
 
   HeapRegion* hr;
   if (in_young_gc_mode()) {
@@ -3135,14 +2939,9 @@
       double predicted_time_ms = predict_region_elapsed_time_ms(hr, true);
       time_remaining_ms -= predicted_time_ms;
       predicted_pause_time_ms += predicted_time_ms;
-      if (hr == pop_region) {
-        // The popular region was young.  Skip over it.
-        assert(hr->in_collection_set(), "It's the pop region.");
-      } else {
-        assert(!hr->in_collection_set(), "It's not the pop region.");
-        add_to_collection_set(hr);
-        record_cset_region(hr, true);
-      }
+      assert(!hr->in_collection_set(), "invariant");
+      add_to_collection_set(hr);
+      record_cset_region(hr, true);
       max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes);
       if (G1PolicyVerbose > 0) {
         gclog_or_tty->print_cr("  Added [" PTR_FORMAT ", " PTR_FORMAT") to CS.",
@@ -3165,10 +2964,6 @@
       // don't bother adding more regions...
       goto choose_collection_set_end;
     }
-  } else if (pop_region != NULL) {
-    // We're not in young mode, and we chose a popular region; don't choose
-    // any more.
-    return;
   }
 
   if (!in_young_gc_mode() || !full_young_gcs()) {
@@ -3178,7 +2973,7 @@
     do {
       hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms,
                                                       avg_prediction);
-      if (hr != NULL && !hr->popular()) {
+      if (hr != NULL) {
         double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
         time_remaining_ms -= predicted_time_ms;
         predicted_pause_time_ms += predicted_time_ms;
@@ -3225,8 +3020,8 @@
 }
 
 void G1CollectorPolicy_BestRegionsFirst::
-record_collection_pause_end(bool popular, bool abandoned) {
-  G1CollectorPolicy::record_collection_pause_end(popular, abandoned);
+record_collection_pause_end(bool abandoned) {
+  G1CollectorPolicy::record_collection_pause_end(abandoned);
   assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -47,7 +47,6 @@
   }
 
 class MainBodySummary;
-class PopPreambleSummary;
 
 class PauseSummary: public CHeapObj {
   define_num_seq(total)
@@ -55,7 +54,6 @@
 
 public:
   virtual MainBodySummary*    main_body_summary()    { return NULL; }
-  virtual PopPreambleSummary* pop_preamble_summary() { return NULL; }
 };
 
 class MainBodySummary: public CHeapObj {
@@ -75,36 +73,13 @@
   define_num_seq(clear_ct)  // parallel only
 };
 
-class PopPreambleSummary: public CHeapObj {
-  define_num_seq(pop_preamble)
-    define_num_seq(pop_update_rs)
-    define_num_seq(pop_scan_rs)
-    define_num_seq(pop_closure_app)
-    define_num_seq(pop_evacuation)
-    define_num_seq(pop_other)
-};
-
-class NonPopSummary: public PauseSummary,
-                     public MainBodySummary {
+class Summary: public PauseSummary,
+               public MainBodySummary {
 public:
   virtual MainBodySummary*    main_body_summary()    { return this; }
 };
 
-class PopSummary: public PauseSummary,
-                  public MainBodySummary,
-                  public PopPreambleSummary {
-public:
-  virtual MainBodySummary*    main_body_summary()    { return this; }
-  virtual PopPreambleSummary* pop_preamble_summary() { return this; }
-};
-
-class NonPopAbandonedSummary: public PauseSummary {
-};
-
-class PopAbandonedSummary: public PauseSummary,
-                           public PopPreambleSummary {
-public:
-  virtual PopPreambleSummary* pop_preamble_summary() { return this; }
+class AbandonedSummary: public PauseSummary {
 };
 
 class G1CollectorPolicy: public CollectorPolicy {
@@ -146,10 +121,6 @@
   double _cur_satb_drain_time_ms;
   double _cur_clear_ct_time_ms;
   bool   _satb_drain_time_set;
-  double _cur_popular_preamble_start_ms;
-  double _cur_popular_preamble_time_ms;
-  double _cur_popular_compute_rc_time_ms;
-  double _cur_popular_evac_time_ms;
 
   double _cur_CH_strong_roots_end_sec;
   double _cur_CH_strong_roots_dur_ms;
@@ -173,10 +144,8 @@
   TruncatedSeq* _concurrent_mark_remark_times_ms;
   TruncatedSeq* _concurrent_mark_cleanup_times_ms;
 
-  NonPopSummary*           _non_pop_summary;
-  PopSummary*              _pop_summary;
-  NonPopAbandonedSummary*  _non_pop_abandoned_summary;
-  PopAbandonedSummary*     _pop_abandoned_summary;
+  Summary*           _summary;
+  AbandonedSummary*  _abandoned_summary;
 
   NumberSeq* _all_pause_times_ms;
   NumberSeq* _all_full_gc_times_ms;
@@ -210,18 +179,6 @@
   double* _par_last_obj_copy_times_ms;
   double* _par_last_termination_times_ms;
 
-  // there are two pases during popular pauses, so we need to store
-  // somewhere the results of the first pass
-  double* _pop_par_last_update_rs_start_times_ms;
-  double* _pop_par_last_update_rs_times_ms;
-  double* _pop_par_last_update_rs_processed_buffers;
-  double* _pop_par_last_scan_rs_start_times_ms;
-  double* _pop_par_last_scan_rs_times_ms;
-  double* _pop_par_last_closure_app_times_ms;
-
-  double _pop_compute_rc_start;
-  double _pop_evac_start;
-
   // indicates that we are in young GC mode
   bool _in_young_gc_mode;
 
@@ -634,8 +591,7 @@
                          NumberSeq* calc_other_times_ms) const;
 
   void print_summary (PauseSummary* stats) const;
-  void print_abandoned_summary(PauseSummary* non_pop_summary,
-                               PauseSummary* pop_summary) const;
+  void print_abandoned_summary(PauseSummary* summary) const;
 
   void print_summary (int level, const char* str, NumberSeq* seq) const;
   void print_summary_sd (int level, const char* str, NumberSeq* seq) const;
@@ -856,9 +812,6 @@
   virtual void record_collection_pause_start(double start_time_sec,
                                              size_t start_used);
 
-  virtual void record_popular_pause_preamble_start();
-  virtual void record_popular_pause_preamble_end();
-
   // Must currently be called while the world is stopped.
   virtual void record_concurrent_mark_init_start();
   virtual void record_concurrent_mark_init_end();
@@ -881,7 +834,7 @@
   virtual void record_collection_pause_end_CH_strong_roots();
   virtual void record_collection_pause_end_G1_strong_roots();
 
-  virtual void record_collection_pause_end(bool popular, bool abandoned);
+  virtual void record_collection_pause_end(bool abandoned);
 
   // Record the fact that a full collection occurred.
   virtual void record_full_collection_start();
@@ -990,12 +943,6 @@
     _cur_aux_times_ms[i] += ms;
   }
 
-  void record_pop_compute_rc_start();
-  void record_pop_compute_rc_end();
-
-  void record_pop_evac_start();
-  void record_pop_evac_end();
-
   // Record the fact that "bytes" bytes allocated in a region.
   void record_before_bytes(size_t bytes);
   void record_after_bytes(size_t bytes);
@@ -1008,9 +955,7 @@
   // Choose a new collection set.  Marks the chosen regions as being
   // "in_collection_set", and links them together.  The head and number of
   // the collection set are available via access methods.
-  // If "pop_region" is non-NULL, it is a popular region that has already
-  // been added to the collection set.
-  virtual void choose_collection_set(HeapRegion* pop_region = NULL) = 0;
+  virtual void choose_collection_set() = 0;
 
   void clear_collection_set() { _collection_set = NULL; }
 
@@ -1018,9 +963,6 @@
   // current collection set.
   HeapRegion* collection_set() { return _collection_set; }
 
-  // Sets the collection set to the given single region.
-  virtual void set_single_region_collection_set(HeapRegion* hr);
-
   // The number of elements in the current collection set.
   size_t collection_set_size() { return _collection_set_size; }
 
@@ -1203,7 +1145,7 @@
   // If the estimated is less then desirable, resize if possible.
   void expand_if_possible(size_t numRegions);
 
-  virtual void choose_collection_set(HeapRegion* pop_region = NULL);
+  virtual void choose_collection_set();
   virtual void record_collection_pause_start(double start_time_sec,
                                              size_t start_used);
   virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes,
@@ -1214,9 +1156,8 @@
   G1CollectorPolicy_BestRegionsFirst() {
     _collectionSetChooser = new CollectionSetChooser();
   }
-  void record_collection_pause_end(bool popular, bool abandoned);
+  void record_collection_pause_end(bool abandoned);
   bool should_do_collection_pause(size_t word_size);
-  virtual void set_single_region_collection_set(HeapRegion* hr);
   // This is not needed any more, after the CSet choosing code was
   // changed to use the pause prediction work. But let's leave the
   // hook in just in case.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -157,7 +157,6 @@
 class G1PrepareCompactClosure: public HeapRegionClosure {
   ModRefBarrierSet* _mrbs;
   CompactPoint _cp;
-  bool _popular_only;
 
   void free_humongous_region(HeapRegion* hr) {
     HeapWord* bot = hr->bottom();
@@ -172,17 +171,11 @@
   }
 
 public:
-  G1PrepareCompactClosure(CompactibleSpace* cs, bool popular_only) :
+  G1PrepareCompactClosure(CompactibleSpace* cs) :
     _cp(NULL, cs, cs->initialize_threshold()),
-    _mrbs(G1CollectedHeap::heap()->mr_bs()),
-    _popular_only(popular_only)
+    _mrbs(G1CollectedHeap::heap()->mr_bs())
   {}
   bool doHeapRegion(HeapRegion* hr) {
-    if (_popular_only && !hr->popular())
-      return true; // terminate early
-    else if (!_popular_only && hr->popular())
-      return false; // skip this one.
-
     if (hr->isHumongous()) {
       if (hr->startsHumongous()) {
         oop obj = oop(hr->bottom());
@@ -203,20 +196,15 @@
     return false;
   }
 };
-// Stolen verbatim from g1CollectedHeap.cpp
+
+// Finds the first HeapRegion.
 class FindFirstRegionClosure: public HeapRegionClosure {
   HeapRegion* _a_region;
-  bool _find_popular;
 public:
-  FindFirstRegionClosure(bool find_popular) :
-    _a_region(NULL), _find_popular(find_popular) {}
+  FindFirstRegionClosure() : _a_region(NULL) {}
   bool doHeapRegion(HeapRegion* r) {
-    if (r->popular() == _find_popular) {
-      _a_region = r;
-      return true;
-    } else {
-      return false;
-    }
+    _a_region = r;
+    return true;
   }
   HeapRegion* result() { return _a_region; }
 };
@@ -242,30 +230,15 @@
   TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty);
   GenMarkSweep::trace("2");
 
-  // First we compact the popular regions.
-  if (G1NumPopularRegions > 0) {
-    CompactibleSpace* sp = g1h->first_compactible_space();
-    FindFirstRegionClosure cl(true /*find_popular*/);
-    g1h->heap_region_iterate(&cl);
-    HeapRegion *r = cl.result();
-    assert(r->popular(), "should have found a popular region.");
-    assert(r == sp, "first popular heap region should "
-                    "== first compactible space");
-    G1PrepareCompactClosure blk(sp, true/*popular_only*/);
-    g1h->heap_region_iterate(&blk);
-  }
-
-  // Now we do the regular regions.
-  FindFirstRegionClosure cl(false /*find_popular*/);
+  FindFirstRegionClosure cl;
   g1h->heap_region_iterate(&cl);
   HeapRegion *r = cl.result();
-  assert(!r->popular(), "should have founda non-popular region.");
   CompactibleSpace* sp = r;
   if (r->isHumongous() && oop(r->bottom())->is_gc_marked()) {
     sp = r->next_compaction_space();
   }
 
-  G1PrepareCompactClosure blk(sp, false/*popular_only*/);
+  G1PrepareCompactClosure blk(sp);
   g1h->heap_region_iterate(&blk);
 
   CompactPoint perm_cp(pg, NULL, NULL);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -580,9 +580,7 @@
   virtual void do_oop(oop* p) {
     HeapRegion* to = _g1->heap_region_containing(*p);
     if (to->in_collection_set()) {
-      if (to->rem_set()->add_reference(p, 0)) {
-        _g1->schedule_popular_region_evac(to);
-      }
+      to->rem_set()->add_reference(p, 0);
     }
   }
 };
@@ -1024,9 +1022,8 @@
     gclog_or_tty->print_cr("    %d occupied cards represented.",
                            blk.occupied());
     gclog_or_tty->print_cr("    Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
-                           " %s, cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
+                           ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
                            blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
-                           (blk.max_mem_sz_region()->popular() ? "POP" : ""),
                            (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
                            (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
     gclog_or_tty->print_cr("    Did %d coarsenings.",
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -65,7 +65,6 @@
   HeapRegion* to = _g1->heap_region_containing(obj);
   // The test below could be optimized by applying a bit op to to and from.
   if (to != NULL && from != NULL && from != to) {
-    bool update_delayed = false;
     // There is a tricky infinite loop if we keep pushing
     // self forwarding pointers onto our _new_refs list.
     // The _par_traversal_in_progress flag is true during the collection pause,
@@ -77,10 +76,7 @@
       // or processed (if an evacuation failure occurs) at the end
       // of the collection.
       // See HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do().
-      update_delayed = true;
-    }
-
-    if (!to->popular() && !update_delayed) {
+    } else {
 #if G1_REM_SET_LOGGING
       gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS"
                              " for region [" PTR_FORMAT ", " PTR_FORMAT ")",
@@ -88,9 +84,7 @@
                              to->bottom(), to->end());
 #endif
       assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
-      if (to->rem_set()->add_reference(p, tid)) {
-        _g1->schedule_popular_region_evac(to);
-      }
+      to->rem_set()->add_reference(p, tid);
     }
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -185,15 +185,9 @@
   product(intx, G1InefficientPausePct, 80,                                  \
           "Threshold of an 'inefficient' pauses (as % of cum efficiency.")  \
                                                                             \
-  product(intx, G1RSPopLimit, 32768,                                        \
-          "Limit that defines popularity.  Should go away! XXX")            \
-                                                                            \
   develop(bool, G1RSCountHisto, false,                                      \
           "If true, print a histogram of RS occupancies after each pause")  \
                                                                             \
-  product(intx, G1ObjPopLimit, 256,                                         \
-          "Limit that defines popularity for an object.")                   \
-                                                                            \
   product(bool, G1TraceFileOverwrite, false,                                \
           "Allow the trace file to be overwritten")                         \
                                                                             \
@@ -201,16 +195,6 @@
           "When > 0, print the occupancies of the <n> best and worst"       \
           "regions.")                                                       \
                                                                             \
-  develop(bool, G1TracePopularity, false,                                   \
-          "When true, provide detailed tracing of popularity.")             \
-                                                                            \
-  product(bool, G1SummarizePopularity, false,                               \
-          "When true, provide end-of-run-summarization of popularity.")     \
-                                                                            \
-  product(intx, G1NumPopularRegions, 1,                                     \
-          "Number of regions reserved to hold popular objects.  "           \
-          "Should go away later.")                                          \
-                                                                            \
   develop(bool, G1PrintParCleanupStats, false,                              \
           "When true, print extra stats about parallel cleanup.")           \
                                                                             \
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -104,7 +104,6 @@
         HeapRegion* to   = _g1h->heap_region_containing(*p);
         if (from != NULL && to != NULL &&
             from != to &&
-            !to->popular() &&
             !to->isHumongous()) {
           jbyte cv_obj = *_bs->byte_for_const(_containing_obj);
           jbyte cv_field = *_bs->byte_for_const(p);
@@ -285,8 +284,6 @@
   }
   zero_marked_bytes();
   set_sort_index(-1);
-  if ((uintptr_t)bottom() >= (uintptr_t)g1h->popular_object_boundary())
-    set_popular(false);
 
   _offsets.resize(HeapRegion::GrainWords);
   init_top_at_mark_start();
@@ -371,7 +368,6 @@
     _next_in_special_set(NULL), _orig_end(NULL),
     _claimed(InitialClaimValue), _evacuation_failed(false),
     _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1),
-    _popularity(NotPopular),
     _young_type(NotYoung), _next_young_region(NULL),
     _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
     _rem_set(NULL), _zfs(NotZeroFilled)
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -238,15 +238,6 @@
   // See "sort_index" method.  -1 means is not in the array.
   int _sort_index;
 
-  // Means it has (or at least had) a very large RS, and should not be
-  // considered for membership in a collection set.
-  enum PopularityState {
-    NotPopular,
-    PopularPending,
-    Popular
-  };
-  PopularityState _popularity;
-
   // <PREDICTION>
   double _gc_efficiency;
   // </PREDICTION>
@@ -433,10 +424,6 @@
     _next_in_special_set = r;
   }
 
-  bool is_reserved() {
-    return popular();
-  }
-
   bool is_on_free_list() {
     return _is_on_free_list;
   }
@@ -609,23 +596,6 @@
     init_top_at_mark_start();
   }
 
-  bool popular() { return _popularity == Popular; }
-  void set_popular(bool b) {
-    if (b) {
-      _popularity = Popular;
-    } else {
-      _popularity = NotPopular;
-    }
-  }
-  bool popular_pending() { return _popularity == PopularPending; }
-  void set_popular_pending(bool b) {
-    if (b) {
-      _popularity = PopularPending;
-    } else {
-      _popularity = NotPopular;
-    }
-  }
-
   // <PREDICTION>
   void calc_gc_efficiency(void);
   double gc_efficiency() { return _gc_efficiency;}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -188,32 +188,6 @@
   // the _outgoing_region_map.
   void clear_outgoing_entries();
 
-#if MAYBE
-  // Audit the given card index.
-  void audit_card(size_t card_num, HeapRegion* hr, u2* rc_arr,
-                  HeapRegionRemSet* empty_cards, size_t* one_obj_cards);
-
-  // Assumes that "audit_stage1" has been called for "hr", to set up
-  // "shadow" and "new_rs" appropriately.  Identifies individual popular
-  // objects; returns "true" if any are found.
-  bool audit_find_pop(HeapRegion* hr, u2* rc_arr);
-
-  // Assumes that "audit_stage1" has been called for "hr", to set up
-  // "shadow" and "new_rs" appropriately.  Identifies individual popular
-  // objects, and determines the number of entries in "new_rs" if any such
-  // popular objects are ignored.  If this is sufficiently small, returns
-  // "false" to indicate that a constraint should not be introduced.
-  // Otherwise, returns "true" to indicate that we should go ahead with
-  // adding the constraint.
-  bool audit_stag(HeapRegion* hr, u2* rc_arr);
-
-
-  u2* alloc_rc_array();
-
-  SeqHeapRegionRemSet* audit_post(u2* rc_arr, size_t multi_obj_crds,
-                                  SeqHeapRegionRemSet* empty_cards);
-#endif
-
   enum ParIterState { Unclaimed, Claimed, Complete };
   ParIterState _iter_state;
 
@@ -261,16 +235,14 @@
 
   /* Used in the sequential case.  Returns "true" iff this addition causes
      the size limit to be reached. */
-  bool add_reference(oop* from) {
+  void add_reference(oop* from) {
     _other_regions.add_reference(from);
-    return false;
   }
 
   /* Used in the parallel case.  Returns "true" iff this addition causes
      the size limit to be reached. */
-  bool add_reference(oop* from, int tid) {
+  void add_reference(oop* from, int tid) {
     _other_regions.add_reference(from, tid);
-    return false;
   }
 
   // Records the fact that the current region contains an outgoing
@@ -338,20 +310,6 @@
   }
   void print() const;
 
-#if MAYBE
-  // We are about to introduce a constraint, requiring the collection time
-  // of the region owning this RS to be <= "hr", and forgetting pointers
-  // from the owning region to "hr."  Before doing so, examines this rem
-  // set for pointers to "hr", possibly identifying some popular objects.,
-  // and possibly finding some cards to no longer contain pointers to "hr",
-  //
-  // These steps may prevent the the constraint from being necessary; in
-  // which case returns a set of cards now thought to contain no pointers
-  // into HR.  In the normal (I assume) case, returns NULL, indicating that
-  // we should go ahead and add the constraint.
-  virtual SeqHeapRegionRemSet* audit(HeapRegion* hr) = 0;
-#endif
-
   // Called during a stop-world phase to perform any deferred cleanups.
   // The second version may be called by parallel threads after then finish
   // collection work.
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -74,7 +74,6 @@
     //       [first, cur)
     HeapRegion* curhr = _regions.at(cur);
     if (curhr->is_empty()
-        && !curhr->is_reserved()
         && (first == cur
             || (_regions.at(cur-1)->end() ==
                 curhr->bottom()))) {
@@ -121,35 +120,27 @@
   }
 }
 
-void HeapRegionSeq::print_empty_runs(bool reserved_are_empty) {
+void HeapRegionSeq::print_empty_runs() {
   int empty_run = 0;
   int n_empty = 0;
-  bool at_least_one_reserved = false;
   int empty_run_start;
   for (int i = 0; i < _regions.length(); i++) {
     HeapRegion* r = _regions.at(i);
     if (r->continuesHumongous()) continue;
-    if (r->is_empty() && (reserved_are_empty || !r->is_reserved())) {
+    if (r->is_empty()) {
       assert(!r->isHumongous(), "H regions should not be empty.");
       if (empty_run == 0) empty_run_start = i;
       empty_run++;
       n_empty++;
-      if (r->is_reserved()) {
-        at_least_one_reserved = true;
-      }
     } else {
       if (empty_run > 0) {
         gclog_or_tty->print("  %d:%d", empty_run_start, empty_run);
-        if (reserved_are_empty && at_least_one_reserved)
-          gclog_or_tty->print("(R)");
         empty_run = 0;
-        at_least_one_reserved = false;
       }
     }
   }
   if (empty_run > 0) {
     gclog_or_tty->print(" %d:%d", empty_run_start, empty_run);
-    if (reserved_are_empty && at_least_one_reserved) gclog_or_tty->print("(R)");
   }
   gclog_or_tty->print_cr(" [tot = %d]", n_empty);
 }
@@ -193,7 +184,6 @@
   int cur = first;
   while (cur >= 0 &&
          (_regions.at(cur)->is_empty()
-          && !_regions.at(cur)->is_reserved()
           && (first == cur
               || (_regions.at(cur+1)->bottom() ==
                   _regions.at(cur)->end())))) {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -104,8 +104,7 @@
 
   void print();
 
-  // Prints out runs of empty regions.  If the arg is "true" reserved
-  // (popular regions are considered "empty".
-  void print_empty_runs(bool reserved_are_empty);
+  // Prints out runs of empty regions.
+  void print_empty_runs();
 
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -43,16 +43,9 @@
   JvmtiGCForAllocationMarker jgcm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   GCCauseSetter x(g1h, GCCause::_g1_inc_collection_pause);
-  g1h->do_collection_pause_at_safepoint(NULL);
+  g1h->do_collection_pause_at_safepoint();
 }
 
-void VM_G1PopRegionCollectionPause::doit() {
-  JvmtiGCForAllocationMarker jgcm;
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  g1h->do_collection_pause_at_safepoint(_pop_region);
-}
-
-
 void VM_CGC_Operation::doit() {
   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -77,20 +77,6 @@
   }
 };
 
-class VM_G1PopRegionCollectionPause: public VM_GC_Operation {
-  HeapRegion* _pop_region;
- public:
-  VM_G1PopRegionCollectionPause(int gc_count_before, HeapRegion* pop_region) :
-    VM_GC_Operation(gc_count_before),
-    _pop_region(pop_region)
-  {}
-  virtual VMOp_Type type() const { return VMOp_G1PopRegionCollectionPause; }
-  virtual void doit();
-  virtual const char* name() const {
-    return "garbage-first popular region collection pause";
-  }
-};
-
 // Concurrent GC stop-the-world operations such as initial and final mark;
 // consider sharing these with CMS's counterparts.
 class VM_CGC_Operation: public VM_Operation {
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -34,10 +34,12 @@
                                        Generation* old_gen_,
                                        int thread_num_,
                                        ObjToScanQueueSet* work_queue_set_,
+                                       GrowableArray<oop>**  overflow_stack_set_,
                                        size_t desired_plab_sz_,
                                        ParallelTaskTerminator& term_) :
-  _to_space(to_space_), _old_gen(old_gen_), _thread_num(thread_num_),
+  _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
   _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
+  _overflow_stack(overflow_stack_set_[thread_num_]),
   _ageTable(false), // false ==> not the global age table, no perf data.
   _to_space_alloc_buffer(desired_plab_sz_),
   _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
@@ -81,7 +83,7 @@
   assert(old->is_objArray(), "must be obj array");
   assert(old->is_forwarded(), "must be forwarded");
   assert(Universe::heap()->is_in_reserved(old), "must be in heap.");
-  assert(!_old_gen->is_in(old), "must be in young generation.");
+  assert(!old_gen()->is_in(old), "must be in young generation.");
 
   objArrayOop obj = objArrayOop(old->forwardee());
   // Process ParGCArrayScanChunk elements now
@@ -119,26 +121,68 @@
 
 void ParScanThreadState::trim_queues(int max_size) {
   ObjToScanQueue* queue = work_queue();
-  while (queue->size() > (juint)max_size) {
-    oop obj_to_scan;
-    if (queue->pop_local(obj_to_scan)) {
-      note_pop();
-
-      if ((HeapWord *)obj_to_scan < young_old_boundary()) {
-        if (obj_to_scan->is_objArray() &&
-            obj_to_scan->is_forwarded() &&
-            obj_to_scan->forwardee() != obj_to_scan) {
-          scan_partial_array_and_push_remainder(obj_to_scan);
+  do {
+    while (queue->size() > (juint)max_size) {
+      oop obj_to_scan;
+      if (queue->pop_local(obj_to_scan)) {
+        note_pop();
+        if ((HeapWord *)obj_to_scan < young_old_boundary()) {
+          if (obj_to_scan->is_objArray() &&
+              obj_to_scan->is_forwarded() &&
+              obj_to_scan->forwardee() != obj_to_scan) {
+            scan_partial_array_and_push_remainder(obj_to_scan);
+          } else {
+            // object is in to_space
+            obj_to_scan->oop_iterate(&_to_space_closure);
+          }
         } else {
-          // object is in to_space
-          obj_to_scan->oop_iterate(&_to_space_closure);
+          // object is in old generation
+          obj_to_scan->oop_iterate(&_old_gen_closure);
         }
-      } else {
-        // object is in old generation
-        obj_to_scan->oop_iterate(&_old_gen_closure);
       }
     }
+    // For the  case of compressed oops, we have a private, non-shared
+    // overflow stack, so we eagerly drain it so as to more evenly
+    // distribute load early. Note: this may be good to do in
+    // general rather than delay for the final stealing phase.
+    // If applicable, we'll transfer a set of objects over to our
+    // work queue, allowing them to be stolen and draining our
+    // private overflow stack.
+  } while (ParGCTrimOverflow && young_gen()->take_from_overflow_list(this));
+}
+
+bool ParScanThreadState::take_from_overflow_stack() {
+  assert(ParGCUseLocalOverflow, "Else should not call");
+  assert(young_gen()->overflow_list() == NULL, "Error");
+  ObjToScanQueue* queue = work_queue();
+  GrowableArray<oop>* of_stack = overflow_stack();
+  uint num_overflow_elems = of_stack->length();
+  uint num_take_elems     = MIN2(MIN2((queue->max_elems() - queue->size())/4,
+                                      (juint)ParGCDesiredObjsFromOverflowList),
+                                 num_overflow_elems);
+  // Transfer the most recent num_take_elems from the overflow
+  // stack to our work queue.
+  for (size_t i = 0; i != num_take_elems; i++) {
+    oop cur = of_stack->pop();
+    oop obj_to_push = cur->forwardee();
+    assert(Universe::heap()->is_in_reserved(cur), "Should be in heap");
+    assert(!old_gen()->is_in_reserved(cur), "Should be in young gen");
+    assert(Universe::heap()->is_in_reserved(obj_to_push), "Should be in heap");
+    if (should_be_partially_scanned(obj_to_push, cur)) {
+      assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
+      obj_to_push = cur;
+    }
+    bool ok = queue->push(obj_to_push);
+    assert(ok, "Should have succeeded");
   }
+  assert(young_gen()->overflow_list() == NULL, "Error");
+  return num_take_elems > 0;  // was something transferred?
+}
+
+void ParScanThreadState::push_on_overflow_stack(oop p) {
+  assert(ParGCUseLocalOverflow, "Else should not call");
+  overflow_stack()->push(p);
+  assert(young_gen()->overflow_list() == NULL, "Error");
 }
 
 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
@@ -213,6 +257,7 @@
                         ParNewGeneration&       gen,
                         Generation&             old_gen,
                         ObjToScanQueueSet&      queue_set,
+                        GrowableArray<oop>**    overflow_stacks_,
                         size_t                  desired_plab_sz,
                         ParallelTaskTerminator& term);
   inline ParScanThreadState& thread_sate(int i);
@@ -235,6 +280,7 @@
 ParScanThreadStateSet::ParScanThreadStateSet(
   int num_threads, Space& to_space, ParNewGeneration& gen,
   Generation& old_gen, ObjToScanQueueSet& queue_set,
+  GrowableArray<oop>** overflow_stack_set_,
   size_t desired_plab_sz, ParallelTaskTerminator& term)
   : ResourceArray(sizeof(ParScanThreadState), num_threads),
     _gen(gen), _next_gen(old_gen), _term(term),
@@ -245,7 +291,7 @@
   for (int i = 0; i < num_threads; ++i) {
     new ((ParScanThreadState*)_data + i)
         ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
-                           desired_plab_sz, term);
+                           overflow_stack_set_, desired_plab_sz, term);
   }
 }
 
@@ -425,8 +471,7 @@
   ResourceMark rm;
   HandleMark hm;
   // We would need multiple old-gen queues otherwise.
-  guarantee(gch->n_gens() == 2,
-     "Par young collection currently only works with one older gen.");
+  assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen.");
 
   Generation* old_gen = gch->next_gen(_gen);
 
@@ -473,6 +518,17 @@
   for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
     _task_queues->queue(i2)->initialize();
 
+  _overflow_stacks = NEW_C_HEAP_ARRAY(GrowableArray<oop>*, ParallelGCThreads);
+  guarantee(_overflow_stacks != NULL, "Overflow stack set allocation failure");
+  for (uint i = 0; i < ParallelGCThreads; i++) {
+    if (ParGCUseLocalOverflow) {
+      _overflow_stacks[i] = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true);
+      guarantee(_overflow_stacks[i] != NULL, "Overflow Stack allocation failure.");
+    } else {
+      _overflow_stacks[i] = NULL;
+    }
+  }
+
   if (UsePerfData) {
     EXCEPTION_MARK;
     ResourceMark rm;
@@ -738,7 +794,7 @@
   ParallelTaskTerminator _term(workers->total_workers(), task_queues());
   ParScanThreadStateSet thread_state_set(workers->total_workers(),
                                          *to(), *this, *_next_gen, *task_queues(),
-                                         desired_plab_sz(), _term);
+                                         _overflow_stacks, desired_plab_sz(), _term);
 
   ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
   int n_workers = workers->total_workers();
@@ -1169,36 +1225,77 @@
 }
 #endif
 
+// In case we are using compressed oops, we need to be careful.
+// If the object being pushed is an object array, then its length
+// field keeps track of the "grey boundary" at which the next
+// incremental scan will be done (see ParGCArrayScanChunk).
+// When using compressed oops, this length field is kept in the
+// lower 32 bits of the erstwhile klass word and cannot be used
+// for the overflow chaining pointer (OCP below). As such the OCP
+// would itself need to be compressed into the top 32-bits in this
+// case. Unfortunately, see below, in the event that we have a
+// promotion failure, the node to be pushed on the list can be
+// outside of the Java heap, so the heap-based pointer compression
+// would not work (we would have potential aliasing between C-heap
+// and Java-heap pointers). For this reason, when using compressed
+// oops, we simply use a worker-thread-local, non-shared overflow
+// list in the form of a growable array, with a slightly different
+// overflow stack draining strategy. If/when we start using fat
+// stacks here, we can go back to using (fat) pointer chains
+// (although some performance comparisons would be useful since
+// single global lists have their own performance disadvantages
+// as we were made painfully aware not long ago, see 6786503).
 #define BUSY (oop(0x1aff1aff))
 void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) {
-  // if the object has been forwarded to itself, then we cannot
-  // use the klass pointer for the linked list.  Instead we have
-  // to allocate an oopDesc in the C-Heap and use that for the linked list.
-  // XXX This is horribly inefficient when a promotion failure occurs
-  // and should be fixed. XXX FIX ME !!!
+  assert(is_in_reserved(from_space_obj), "Should be from this generation");
+  if (ParGCUseLocalOverflow) {
+    // In the case of compressed oops, we use a private, not-shared
+    // overflow stack.
+    par_scan_state->push_on_overflow_stack(from_space_obj);
+  } else {
+    assert(!UseCompressedOops, "Error");
+    // if the object has been forwarded to itself, then we cannot
+    // use the klass pointer for the linked list.  Instead we have
+    // to allocate an oopDesc in the C-Heap and use that for the linked list.
+    // XXX This is horribly inefficient when a promotion failure occurs
+    // and should be fixed. XXX FIX ME !!!
 #ifndef PRODUCT
-  Atomic::inc_ptr(&_num_par_pushes);
-  assert(_num_par_pushes > 0, "Tautology");
+    Atomic::inc_ptr(&_num_par_pushes);
+    assert(_num_par_pushes > 0, "Tautology");
 #endif
-  if (from_space_obj->forwardee() == from_space_obj) {
-    oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
-    listhead->forward_to(from_space_obj);
-    from_space_obj = listhead;
+    if (from_space_obj->forwardee() == from_space_obj) {
+      oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
+      listhead->forward_to(from_space_obj);
+      from_space_obj = listhead;
+    }
+    oop observed_overflow_list = _overflow_list;
+    oop cur_overflow_list;
+    do {
+      cur_overflow_list = observed_overflow_list;
+      if (cur_overflow_list != BUSY) {
+        from_space_obj->set_klass_to_list_ptr(cur_overflow_list);
+      } else {
+        from_space_obj->set_klass_to_list_ptr(NULL);
+      }
+      observed_overflow_list =
+        (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
+    } while (cur_overflow_list != observed_overflow_list);
   }
-  oop observed_overflow_list = _overflow_list;
-  oop cur_overflow_list;
-  do {
-    cur_overflow_list = observed_overflow_list;
-    if (cur_overflow_list != BUSY) {
-      from_space_obj->set_klass_to_list_ptr(cur_overflow_list);
-    } else {
-      from_space_obj->set_klass_to_list_ptr(NULL);
-    }
-    observed_overflow_list =
-      (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
-  } while (cur_overflow_list != observed_overflow_list);
 }
 
+bool ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
+  bool res;
+
+  if (ParGCUseLocalOverflow) {
+    res = par_scan_state->take_from_overflow_stack();
+  } else {
+    assert(!UseCompressedOops, "Error");
+    res = take_from_overflow_list_work(par_scan_state);
+  }
+  return res;
+}
+
+
 // *NOTE*: The overflow list manipulation code here and
 // in CMSCollector:: are very similar in shape,
 // except that in the CMS case we thread the objects
@@ -1213,14 +1310,14 @@
 // similar changes might be needed.
 // See CMSCollector::par_take_from_overflow_list() for
 // more extensive documentation comments.
-bool
-ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
+bool ParNewGeneration::take_from_overflow_list_work(ParScanThreadState* par_scan_state) {
   ObjToScanQueue* work_q = par_scan_state->work_queue();
-  assert(work_q->size() == 0, "Should first empty local work queue");
   // How many to take?
-  size_t objsFromOverflow = MIN2((size_t)work_q->max_elems()/4,
+  size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
                                  (size_t)ParGCDesiredObjsFromOverflowList);
 
+  assert(par_scan_state->overflow_stack() == NULL, "Error");
+  assert(!UseCompressedOops, "Error");
   if (_overflow_list == NULL) return false;
 
   // Otherwise, there was something there; try claiming the list.
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -33,8 +33,8 @@
 // but they must be here to allow ParScanClosure::do_oop_work to be defined
 // in genOopClosures.inline.hpp.
 
-typedef OopTaskQueue    ObjToScanQueue;
-typedef OopTaskQueueSet ObjToScanQueueSet;
+typedef OopTaskQueue       ObjToScanQueue;
+typedef OopTaskQueueSet    ObjToScanQueueSet;
 
 // Enable this to get push/pop/steal stats.
 const int PAR_STATS_ENABLED = 0;
@@ -55,6 +55,7 @@
   friend class ParScanThreadStateSet;
  private:
   ObjToScanQueue *_work_queue;
+  GrowableArray<oop>* _overflow_stack;
 
   ParGCAllocBuffer _to_space_alloc_buffer;
 
@@ -79,6 +80,9 @@
   Space* _to_space;
   Space* to_space() { return _to_space; }
 
+  ParNewGeneration* _young_gen;
+  ParNewGeneration* young_gen() const { return _young_gen; }
+
   Generation* _old_gen;
   Generation* old_gen() { return _old_gen; }
 
@@ -112,7 +116,9 @@
 
   ParScanThreadState(Space* to_space_, ParNewGeneration* gen_,
                      Generation* old_gen_, int thread_num_,
-                     ObjToScanQueueSet* work_queue_set_, size_t desired_plab_sz_,
+                     ObjToScanQueueSet* work_queue_set_,
+                     GrowableArray<oop>** overflow_stack_set_,
+                     size_t desired_plab_sz_,
                      ParallelTaskTerminator& term_);
 
  public:
@@ -134,6 +140,11 @@
   // Decrease queue size below "max_size".
   void trim_queues(int max_size);
 
+  // Private overflow stack usage
+  GrowableArray<oop>* overflow_stack() { return _overflow_stack; }
+  bool take_from_overflow_stack();
+  void push_on_overflow_stack(oop p);
+
   // Is new_obj a candidate for scan_partial_array_and_push_remainder method.
   inline bool should_be_partially_scanned(oop new_obj, oop old_obj) const;
 
@@ -287,9 +298,12 @@
         char pad[64 - sizeof(ObjToScanQueue)];  // prevent false sharing
   };
 
-  // The per-thread work queues, available here for stealing.
+  // The per-worker-thread work queues
   ObjToScanQueueSet* _task_queues;
 
+  // Per-worker-thread local overflow stacks
+  GrowableArray<oop>** _overflow_stacks;
+
   // Desired size of survivor space plab's
   PLABStats _plab_stats;
 
@@ -378,13 +392,17 @@
   NOT_PRODUCT(int _overflow_counter;)
   NOT_PRODUCT(bool should_simulate_overflow();)
 
+  // Accessor for overflow list
+  oop overflow_list() { return _overflow_list; }
+
   // Push the given (from-space) object on the global overflow list.
   void push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state);
 
   // If the global overflow list is non-empty, move some tasks from it
-  // onto "work_q" (which must be empty).  No more than 1/4 of the
-  // max_elems of "work_q" are moved.
+  // onto "work_q" (which need not be empty).  No more than 1/4 of the
+  // available space on "work_q" is used.
   bool take_from_overflow_list(ParScanThreadState* par_scan_state);
+  bool take_from_overflow_list_work(ParScanThreadState* par_scan_state);
 
   // The task queues to be used by parallel GC threads.
   ObjToScanQueueSet* task_queues() {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -825,6 +825,7 @@
   if (young_gen()->is_in_reserved(addr)) {
     assert(young_gen()->is_in(addr),
            "addr should be in allocated part of young gen");
+    if (Debugging)  return NULL;  // called from find() in debug.cpp
     Unimplemented();
   } else if (old_gen()->is_in_reserved(addr)) {
     assert(old_gen()->is_in(addr),
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -508,6 +508,7 @@
   assert(destination <= target_end, "sanity");
   assert(destination + _region_data[src_region].data_size() > target_end,
     "region should not fit into target space");
+  assert(is_region_aligned(target_end), "sanity");
 
   size_t split_region = src_region;
   HeapWord* split_destination = destination;
@@ -538,14 +539,12 @@
     //         max(top, max(new_top, clear_top))
     //
     // where clear_top is a new field in SpaceInfo.  Would have to set clear_top
-    // to destination + partial_obj_size, where both have the values passed to
-    // this routine.
+    // to target_end.
     const RegionData* const sr = region(split_region);
     const size_t beg_idx =
       addr_to_region_idx(region_align_up(sr->destination() +
                                          sr->partial_obj_size()));
-    const size_t end_idx =
-      addr_to_region_idx(region_align_up(destination + partial_obj_size));
+    const size_t end_idx = addr_to_region_idx(target_end);
 
     if (TraceParallelOldGCSummaryPhase) {
         gclog_or_tty->print_cr("split:  clearing source_region field in ["
--- a/hotspot/src/share/vm/gc_interface/gcCause.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -60,7 +60,7 @@
     _old_generation_too_full_to_scavenge,
     _adaptive_size_policy,
 
-    _g1_inc_collection_pause, _g1_pop_region_collection_pause,
+    _g1_inc_collection_pause,
 
     _last_ditch_collection,
     _last_gc_cause
--- a/hotspot/src/share/vm/includeDB_core	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_core	Wed Jul 05 16:50:32 2017 +0200
@@ -3154,6 +3154,8 @@
 oopsHierarchy.cpp                       thread_<os_family>.inline.hpp
 
 orderAccess.cpp                         orderAccess.hpp
+orderAccess.cpp                         stubRoutines.hpp
+orderAccess.cpp                         thread.hpp
 
 orderAccess.hpp                         allocation.hpp
 orderAccess.hpp                         os.hpp
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1813,6 +1813,8 @@
                                           oop class_loader2, symbolOop class_name2) {
   if (class_loader1 != class_loader2) {
     return false;
+  } else if (class_name1 == class_name2) {
+    return true;                // skip painful bytewise comparison
   } else {
     ResourceMark rm;
 
@@ -1879,6 +1881,56 @@
    return(is_same_class_package(targetclassloader(), targetclassname()));
 }
 
+/* defined for now in jvm.cpp, for historical reasons *--
+klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle self,
+                                                     symbolOop& simple_name_result, TRAPS) {
+  ...
+}
+*/
+
+// tell if two classes have the same enclosing class (at package level)
+bool instanceKlass::is_same_package_member_impl(instanceKlassHandle class1,
+                                                klassOop class2_oop, TRAPS) {
+  if (class2_oop == class1->as_klassOop())          return true;
+  if (!Klass::cast(class2_oop)->oop_is_instance())  return false;
+  instanceKlassHandle class2(THREAD, class2_oop);
+
+  // must be in same package before we try anything else
+  if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
+    return false;
+
+  // As long as there is an outer1.getEnclosingClass,
+  // shift the search outward.
+  instanceKlassHandle outer1 = class1;
+  for (;;) {
+    // As we walk along, look for equalities between outer1 and class2.
+    // Eventually, the walks will terminate as outer1 stops
+    // at the top-level class around the original class.
+    symbolOop ignore_name;
+    klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_false);
+    if (next == NULL)  break;
+    if (next == class2())  return true;
+    outer1 = instanceKlassHandle(THREAD, next);
+  }
+
+  // Now do the same for class2.
+  instanceKlassHandle outer2 = class2;
+  for (;;) {
+    symbolOop ignore_name;
+    klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_false);
+    if (next == NULL)  break;
+    // Might as well check the new outer against all available values.
+    if (next == class1())  return true;
+    if (next == outer1())  return true;
+    outer2 = instanceKlassHandle(THREAD, next);
+  }
+
+  // If by this point we have not found an equality between the
+  // two classes, we know they are in separate package members.
+  return false;
+}
+
+
 jint instanceKlass::compute_modifier_flags(TRAPS) const {
   klassOop k = as_klassOop();
   jint access = access_flags().as_int();
@@ -2015,9 +2067,11 @@
 
 // Printing
 
+#define BULLET  " - "
+
 void FieldPrinter::do_field(fieldDescriptor* fd) {
-   if (fd->is_static() == (_obj == NULL)) {
-     _st->print("   - ");
+  _st->print(BULLET);
+   if (fd->is_static() || (_obj == NULL)) {
      fd->print_on(_st);
      _st->cr();
    } else {
@@ -2038,7 +2092,7 @@
         value->is_typeArray() &&
         offset          <= (juint) value->length() &&
         offset + length <= (juint) value->length()) {
-      st->print("string: ");
+      st->print(BULLET"string: ");
       Handle h_obj(obj);
       java_lang_String::print(h_obj, st);
       st->cr();
@@ -2046,23 +2100,26 @@
     }
   }
 
-  st->print_cr("fields:");
+  st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
   FieldPrinter print_nonstatic_field(st, obj);
   do_nonstatic_fields(&print_nonstatic_field);
 
   if (as_klassOop() == SystemDictionary::class_klass()) {
+    st->print(BULLET"signature: ");
+    java_lang_Class::print_signature(obj, st);
+    st->cr();
     klassOop mirrored_klass = java_lang_Class::as_klassOop(obj);
-    st->print("   - fake entry for mirror: ");
+    st->print(BULLET"fake entry for mirror: ");
     mirrored_klass->print_value_on(st);
     st->cr();
-    st->print("   - fake entry resolved_constructor: ");
+    st->print(BULLET"fake entry resolved_constructor: ");
     methodOop ctor = java_lang_Class::resolved_constructor(obj);
     ctor->print_value_on(st);
     klassOop array_klass = java_lang_Class::array_klass(obj);
-    st->print("   - fake entry for array: ");
+    st->cr();
+    st->print(BULLET"fake entry for array: ");
     array_klass->print_value_on(st);
     st->cr();
-    st->cr();
   }
 }
 
@@ -2070,6 +2127,28 @@
   st->print("a ");
   name()->print_value_on(st);
   obj->print_address_on(st);
+  if (as_klassOop() == SystemDictionary::string_klass()
+      && java_lang_String::value(obj) != NULL) {
+    ResourceMark rm;
+    int len = java_lang_String::length(obj);
+    int plen = (len < 24 ? len : 12);
+    char* str = java_lang_String::as_utf8_string(obj, 0, plen);
+    st->print(" = \"%s\"", str);
+    if (len > plen)
+      st->print("...[%d]", len);
+  } else if (as_klassOop() == SystemDictionary::class_klass()) {
+    klassOop k = java_lang_Class::as_klassOop(obj);
+    st->print(" = ");
+    if (k != NULL) {
+      k->print_value_on(st);
+    } else {
+      const char* tname = type2name(java_lang_Class::primitive_type(obj));
+      st->print("%s", tname ? tname : "type?");
+    }
+  } else if (java_lang_boxing_object::is_instance(obj)) {
+    st->print(" = ");
+    java_lang_boxing_object::print(obj, st);
+  }
 }
 
 #endif // ndef PRODUCT
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -311,6 +311,22 @@
   bool is_same_class_package(oop classloader2, symbolOop classname2);
   static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2);
 
+  // find an enclosing class (defined where original code was, in jvm.cpp!)
+  klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) {
+    instanceKlassHandle self(THREAD, this->as_klassOop());
+    return compute_enclosing_class_impl(self, simple_name_result, THREAD);
+  }
+  static klassOop compute_enclosing_class_impl(instanceKlassHandle self,
+                                               symbolOop& simple_name_result, TRAPS);
+
+  // tell if two classes have the same enclosing class (at package level)
+  bool is_same_package_member(klassOop class2, TRAPS) {
+    instanceKlassHandle self(THREAD, this->as_klassOop());
+    return is_same_package_member_impl(self, class2, THREAD);
+  }
+  static bool is_same_package_member_impl(instanceKlassHandle self,
+                                          klassOop class2, TRAPS);
+
   // initialization state
   bool is_loaded() const                   { return _init_state >= loaded; }
   bool is_linked() const                   { return _init_state >= linked; }
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -487,6 +487,8 @@
 
 // Printing
 
+#define BULLET  " - "
+
 static const char* state_names[] = {
   "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error"
 };
@@ -497,13 +499,13 @@
   instanceKlass* ik = instanceKlass::cast(klassOop(obj));
   klassKlass::oop_print_on(obj, st);
 
-  st->print(" - instance size:     %d", ik->size_helper());                        st->cr();
-  st->print(" - klass size:        %d", ik->object_size());                        st->cr();
-  st->print(" - access:            "); ik->access_flags().print_on(st);            st->cr();
-  st->print(" - state:             "); st->print_cr(state_names[ik->_init_state]);
-  st->print(" - name:              "); ik->name()->print_value_on(st);             st->cr();
-  st->print(" - super:             "); ik->super()->print_value_on(st);            st->cr();
-  st->print(" - sub:               ");
+  st->print(BULLET"instance size:     %d", ik->size_helper());                        st->cr();
+  st->print(BULLET"klass size:        %d", ik->object_size());                        st->cr();
+  st->print(BULLET"access:            "); ik->access_flags().print_on(st);            st->cr();
+  st->print(BULLET"state:             "); st->print_cr(state_names[ik->_init_state]);
+  st->print(BULLET"name:              "); ik->name()->print_value_on(st);             st->cr();
+  st->print(BULLET"super:             "); ik->super()->print_value_on(st);            st->cr();
+  st->print(BULLET"sub:               ");
   Klass* sub = ik->subklass();
   int n;
   for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) {
@@ -516,12 +518,12 @@
   st->cr();
 
   if (ik->is_interface()) {
-    st->print_cr(" - nof implementors:  %d", ik->nof_implementors());
+    st->print_cr(BULLET"nof implementors:  %d", ik->nof_implementors());
     int print_impl = 0;
     for (int i = 0; i < instanceKlass::implementors_limit; i++) {
       if (ik->implementor(i) != NULL) {
         if (++print_impl == 1)
-          st->print_cr(" - implementor:    ");
+          st->print_cr(BULLET"implementor:    ");
         st->print("   ");
         ik->implementor(i)->print_value_on(st);
       }
@@ -529,34 +531,33 @@
     if (print_impl > 0)  st->cr();
   }
 
-  st->print(" - arrays:            "); ik->array_klasses()->print_value_on(st);     st->cr();
-  st->print(" - methods:           "); ik->methods()->print_value_on(st);           st->cr();
+  st->print(BULLET"arrays:            "); ik->array_klasses()->print_value_on(st);     st->cr();
+  st->print(BULLET"methods:           "); ik->methods()->print_value_on(st);           st->cr();
   if (Verbose) {
     objArrayOop methods = ik->methods();
     for(int i = 0; i < methods->length(); i++) {
       tty->print("%d : ", i); methods->obj_at(i)->print_value(); tty->cr();
     }
   }
-  st->print(" - method ordering:   "); ik->method_ordering()->print_value_on(st);       st->cr();
-  st->print(" - local interfaces:  "); ik->local_interfaces()->print_value_on(st);      st->cr();
-  st->print(" - trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr();
-  st->print(" - constants:         "); ik->constants()->print_value_on(st);         st->cr();
-  st->print(" - class loader:      "); ik->class_loader()->print_value_on(st);      st->cr();
-  st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
-  st->print(" - host class: ");        ik->host_klass()->print_value_on(st);        st->cr();
-  st->print(" - signers:           "); ik->signers()->print_value_on(st);           st->cr();
+  st->print(BULLET"method ordering:   "); ik->method_ordering()->print_value_on(st);       st->cr();
+  st->print(BULLET"local interfaces:  "); ik->local_interfaces()->print_value_on(st);      st->cr();
+  st->print(BULLET"trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr();
+  st->print(BULLET"constants:         "); ik->constants()->print_value_on(st);         st->cr();
+  st->print(BULLET"class loader:      "); ik->class_loader()->print_value_on(st);      st->cr();
+  st->print(BULLET"protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
+  st->print(BULLET"host class:        "); ik->host_klass()->print_value_on(st);        st->cr();
+  st->print(BULLET"signers:           "); ik->signers()->print_value_on(st);           st->cr();
   if (ik->source_file_name() != NULL) {
-    st->print(" - source file:       ");
+    st->print(BULLET"source file:       ");
     ik->source_file_name()->print_value_on(st);
     st->cr();
   }
   if (ik->source_debug_extension() != NULL) {
-    st->print(" - source debug extension:       ");
+    st->print(BULLET"source debug extension:       ");
     ik->source_debug_extension()->print_value_on(st);
     st->cr();
   }
 
-  st->print_cr(" - previous version:       ");
   {
     ResourceMark rm;
     // PreviousVersionInfo objects returned via PreviousVersionWalker
@@ -564,38 +565,43 @@
     // GrowableArray _after_ the PreviousVersionWalker destructor
     // has destroyed the handles.
     {
+      bool have_pv = false;
       PreviousVersionWalker pvw(ik);
       for (PreviousVersionInfo * pv_info = pvw.next_previous_version();
            pv_info != NULL; pv_info = pvw.next_previous_version()) {
+        if (!have_pv)
+          st->print(BULLET"previous version:  ");
+        have_pv = true;
         pv_info->prev_constant_pool_handle()()->print_value_on(st);
       }
-      st->cr();
+      if (have_pv)  st->cr();
     } // pvw is cleaned up
   } // rm is cleaned up
 
   if (ik->generic_signature() != NULL) {
-    st->print(" - generic signature:            ");
+    st->print(BULLET"generic signature: ");
     ik->generic_signature()->print_value_on(st);
+    st->cr();
   }
-  st->print(" - inner classes:     "); ik->inner_classes()->print_value_on(st);     st->cr();
-  st->print(" - java mirror:       "); ik->java_mirror()->print_value_on(st);       st->cr();
-  st->print(" - vtable length      %d  (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable());  st->cr();
-  st->print(" - itable length      %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr();
-  st->print_cr(" - static fields:");
+  st->print(BULLET"inner classes:     "); ik->inner_classes()->print_value_on(st);     st->cr();
+  st->print(BULLET"java mirror:       "); ik->java_mirror()->print_value_on(st);       st->cr();
+  st->print(BULLET"vtable length      %d  (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable());  st->cr();
+  st->print(BULLET"itable length      %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr();
+  st->print_cr(BULLET"---- static fields (%d words):", ik->static_field_size());
   FieldPrinter print_static_field(st);
   ik->do_local_static_fields(&print_static_field);
-  st->print_cr(" - non-static fields:");
-  FieldPrinter print_nonstatic_field(st, obj);
+  st->print_cr(BULLET"---- non-static fields (%d words):", ik->nonstatic_field_size());
+  FieldPrinter print_nonstatic_field(st);
   ik->do_nonstatic_fields(&print_nonstatic_field);
 
-  st->print(" - static oop maps:     ");
+  st->print(BULLET"static oop maps:     ");
   if (ik->static_oop_field_size() > 0) {
     int first_offset = ik->offset_of_static_fields();
     st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1);
   }
   st->cr();
 
-  st->print(" - non-static oop maps: ");
+  st->print(BULLET"non-static oop maps: ");
   OopMapBlock* map     = ik->start_of_nonstatic_oop_maps();
   OopMapBlock* end_map = map + ik->nonstatic_oop_map_size();
   while (map < end_map) {
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1148,6 +1148,27 @@
   return index;
 }
 
+
+// inverse to compute_itable_index
+methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) {
+  assert(instanceKlass::cast(intf)->is_interface(), "sanity check");
+  objArrayOop methods = instanceKlass::cast(intf)->methods();
+
+  int index = itable_index;
+  // Adjust for <clinit>, which is left out of table if first method
+  if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) {
+    index++;
+  }
+
+  if (itable_index < 0 || index >= methods->length())
+    return NULL;                // help caller defend against bad indexes
+
+  methodOop m = (methodOop)methods->obj_at(index);
+  assert(compute_itable_index(m) == itable_index, "correct inverse");
+
+  return m;
+}
+
 void klassVtable::verify(outputStream* st, bool forced) {
   // make sure table is initialized
   if (!Universe::is_fully_initialized()) return;
--- a/hotspot/src/share/vm/oops/klassVtable.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -301,6 +301,8 @@
 
   // Resolving of method to index
   static int compute_itable_index(methodOop m);
+  // ...and back again:
+  static methodOop method_for_itable_index(klassOop klass, int itable_index);
 
   // Debugging/Statistics
   static void print_statistics() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/oops/methodKlass.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodKlass.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -247,9 +247,14 @@
   st->print_cr(" - size of params:    %d",   m->size_of_parameters());
   st->print_cr(" - method size:       %d",   m->method_size());
   st->print_cr(" - vtable index:      %d",   m->_vtable_index);
+  st->print_cr(" - i2i entry:         " INTPTR_FORMAT, m->interpreter_entry());
+  st->print_cr(" - adapter:           " INTPTR_FORMAT, m->adapter());
+  st->print_cr(" - compiled entry     " INTPTR_FORMAT, m->from_compiled_entry());
   st->print_cr(" - code size:         %d",   m->code_size());
-  st->print_cr(" - code start:        " INTPTR_FORMAT, m->code_base());
-  st->print_cr(" - code end (excl):   " INTPTR_FORMAT, m->code_base() + m->code_size());
+  if (m->code_size() != 0) {
+    st->print_cr(" - code start:        " INTPTR_FORMAT, m->code_base());
+    st->print_cr(" - code end (excl):   " INTPTR_FORMAT, m->code_base() + m->code_size());
+  }
   if (m->method_data() != NULL) {
     st->print_cr(" - method data:       " INTPTR_FORMAT, (address)m->method_data());
   }
@@ -293,6 +298,10 @@
     m->code()->print_value_on(st);
     st->cr();
   }
+  if (m->is_native()) {
+    st->print_cr(" - native function:   " INTPTR_FORMAT, m->native_function());
+    st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
+  }
 }
 
 
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -502,12 +502,25 @@
   }
 }
 
+static int max_objArray_print_length = 4;
 
 void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
   assert(obj->is_objArray(), "must be objArray");
+  st->print("a ");
   element_klass()->print_value_on(st);
-  st->print("a [%d] ", objArrayOop(obj)->length());
-  as_klassOop()->klass()->print_value_on(st);
+  int len = objArrayOop(obj)->length();
+  st->print("[%d] ", len);
+  obj->print_address_on(st);
+  if (PrintOopAddress || PrintMiscellaneous && (WizardMode || Verbose)) {
+    st->print("{");
+    for (int i = 0; i < len; i++) {
+      if (i > max_objArray_print_length) {
+        st->print("..."); break;
+      }
+      st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i));
+    }
+    st->print(" }");
+  }
 }
 
 #endif // PRODUCT
--- a/hotspot/src/share/vm/oops/oop.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/oop.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,11 +65,7 @@
 
 void oopDesc::print_address_on(outputStream* st) const {
   if (PrintOopAddress) {
-    st->print("{");
-    if (PrintOopAddress) {
-      st->print(INTPTR_FORMAT, this);
-    }
-    st->print("}");
+    st->print("{"INTPTR_FORMAT"}", this);
   }
 }
 
--- a/hotspot/src/share/vm/opto/block.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/block.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -371,6 +371,7 @@
   Block *_broot;                // Basic block of root
   uint _rpo_ctr;
   CFGLoop* _root_loop;
+  float _outer_loop_freq;       // Outmost loop frequency
 
   // Per node latency estimation, valid only during GCM
   GrowableArray<uint> _node_latency;
@@ -537,6 +538,7 @@
   void compute_loop_depth(int depth);
   void compute_freq(); // compute frequency with loop assuming head freq 1.0f
   void scale_freq();   // scale frequency by loop trip count (including outer loops)
+  float outer_loop_freq() const; // frequency of outer loop
   bool in_loop_nest(Block* b);
   float trip_count() const { return 1.0f / _exit_prob; }
   virtual bool is_loop()  { return true; }
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -232,6 +232,14 @@
     return "disallowed by CompilerOracle";
   }
 
+  if (UseStringCache) {
+    // Do not inline StringCache::profile() method used only at the beginning.
+    if (callee_method->name() == ciSymbol::profile_name() &&
+        callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
+      return "profiling method";
+    }
+  }
+
   return NULL;
 }
 
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -391,7 +391,7 @@
   product(intx, EliminateAllocationArraySizeLimit, 64,                      \
           "Array size (number of elements) limit for scalar replacement")   \
                                                                             \
-  product(bool, UseOptoBiasInlining, true,                                 \
+  product(bool, UseOptoBiasInlining, true,                                  \
           "Generate biased locking code in C2 ideal graph")                 \
                                                                             \
   product(intx, ValueSearchLimit, 1000,                                     \
@@ -410,7 +410,7 @@
           "Miniumum %% of a successor (predecessor) for which block layout "\
           "a will allow a fork (join) in a single chain")                   \
                                                                             \
-  product(bool, BlockLayoutRotateLoops, false,                              \
+  product(bool, BlockLayoutRotateLoops, true,                               \
           "Allow back branches to be fall throughs in the block layour")    \
 
 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/hotspot/src/share/vm/opto/chaitin.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -149,6 +149,9 @@
 #endif
 {
   NOT_PRODUCT( Compile::TracePhase t3("ctorChaitin", &_t_ctorChaitin, TimeCompiler); )
+
+  _high_frequency_lrg = MIN2(float(OPTO_LRG_HIGH_FREQ), _cfg._outer_loop_freq);
+
   uint i,j;
   // Build a list of basic blocks, sorted by frequency
   _blks = NEW_RESOURCE_ARRAY( Block *, _cfg._num_blocks );
--- a/hotspot/src/share/vm/opto/chaitin.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -338,6 +338,8 @@
 
   Block **_blks;                // Array of blocks sorted by frequency for coalescing
 
+  float _high_frequency_lrg;    // Frequency at which LRG will be spilled for debug info
+
 #ifndef PRODUCT
   bool _trace_spilling;
 #endif
@@ -360,6 +362,8 @@
 
   uint n2lidx( const Node *n ) const { return _names[n->_idx]; }
 
+  float high_frequency_lrg() const { return _high_frequency_lrg; }
+
 #ifndef PRODUCT
   bool trace_spilling() const { return _trace_spilling; }
 #endif
--- a/hotspot/src/share/vm/opto/classes.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -218,6 +218,8 @@
 macro(StoreP)
 macro(StoreN)
 macro(StrComp)
+macro(StrEquals)
+macro(StrIndexOf)
 macro(SubD)
 macro(SubF)
 macro(SubI)
--- a/hotspot/src/share/vm/opto/coalesce.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/coalesce.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -473,7 +473,7 @@
         } // End of is two-adr
 
         // Insert a copy at a debug use for a lrg which has high frequency
-        if( (b->_freq < OPTO_DEBUG_SPLIT_FREQ) && n->is_MachSafePoint() ) {
+        if( b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(_phc._cfg._bbs) ) {
           // Walk the debug inputs to the node and check for lrg freq
           JVMState* jvms = n->jvms();
           uint debug_start = jvms ? jvms->debug_start() : 999999;
@@ -487,7 +487,7 @@
             LRG &lrg = lrgs(nidx);
 
             // If this lrg has a high frequency use/def
-            if( lrg._maxfreq >= OPTO_LRG_HIGH_FREQ ) {
+            if( lrg._maxfreq >= _phc.high_frequency_lrg() ) {
               // If the live range is also live out of this block (like it
               // would be for a fast/slow idiom), the normal spill mechanism
               // does an excellent job.  If it is not live out of this block
--- a/hotspot/src/share/vm/opto/gcm.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -438,6 +438,12 @@
 #endif
   assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrComp),
          "String compare is only known 'load' that does not conflict with any stores");
+  assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrEquals),
+         "String equals is a 'load' that does not conflict with any stores");
+  assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOf),
+         "String indexOf is a 'load' that does not conflict with any stores");
+  assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_AryEq),
+         "Arrays equals is a 'load' that do not conflict with any stores");
 
   if (!C->alias_type(load_alias_idx)->is_rewritable()) {
     // It is impossible to spoil this load by putting stores before it,
@@ -1374,6 +1380,9 @@
   _root_loop->_freq = 1.0;
   _root_loop->scale_freq();
 
+  // Save outmost loop frequency for LRG frequency threshold
+  _outer_loop_freq = _root_loop->outer_loop_freq();
+
   // force paths ending at uncommon traps to be infrequent
   if (!C->do_freq_based_layout()) {
     Block_List worklist;
@@ -1898,6 +1907,7 @@
 // Do a top down traversal of loop tree (visit outer loops first.)
 void CFGLoop::scale_freq() {
   float loop_freq = _freq * trip_count();
+  _freq = loop_freq;
   for (int i = 0; i < _members.length(); i++) {
     CFGElement* s = _members.at(i);
     float block_freq = s->_freq * loop_freq;
@@ -1912,6 +1922,14 @@
   }
 }
 
+// Frequency of outer loop
+float CFGLoop::outer_loop_freq() const {
+  if (_child != NULL) {
+    return _child->_freq;
+  }
+  return _freq;
+}
+
 #ifndef PRODUCT
 //------------------------------dump_tree--------------------------------------
 void CFGLoop::dump_tree() const {
--- a/hotspot/src/share/vm/opto/lcm.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -137,6 +137,8 @@
       if( mach->in(2) != val ) continue;
       break;                    // Found a memory op?
     case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf:
     case Op_AryEq:
       // Not a legit memory op for implicit null check regardless of
       // embedded loads
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -136,6 +136,7 @@
   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);
+  bool inline_string_equals();
   Node* pop_math_arg();
   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
   bool inline_math_native(vmIntrinsics::ID id);
@@ -261,6 +262,7 @@
     switch (id) {
     case vmIntrinsics::_indexOf:
     case vmIntrinsics::_compareTo:
+    case vmIntrinsics::_equals:
     case vmIntrinsics::_equalsC:
       break;  // InlineNatives does not control String.compareTo
     default:
@@ -275,6 +277,9 @@
   case vmIntrinsics::_indexOf:
     if (!SpecialStringIndexOf)  return NULL;
     break;
+  case vmIntrinsics::_equals:
+    if (!SpecialStringEquals)  return NULL;
+    break;
   case vmIntrinsics::_equalsC:
     if (!SpecialArraysEquals)  return NULL;
     break;
@@ -442,6 +447,8 @@
     return inline_string_compareTo();
   case vmIntrinsics::_indexOf:
     return inline_string_indexOf();
+  case vmIntrinsics::_equals:
+    return inline_string_equals();
 
   case vmIntrinsics::_getObject:
     return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false);
@@ -793,6 +800,8 @@
 //------------------------------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();
@@ -830,6 +839,82 @@
   return true;
 }
 
+//------------------------------inline_string_equals------------------------
+bool LibraryCallKit::inline_string_equals() {
+
+  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();
+
+  _sp += 2;
+  Node* argument = pop();  // pop non-receiver first:  it was pushed second
+  Node* receiver = pop();
+
+  // Null check on self without removing any arguments.  The argument
+  // null check technically happens in the wrong place, which can lead to
+  // invalid stack traces when string compare is inlined into a method
+  // which handles NullPointerExceptions.
+  _sp += 2;
+  receiver = do_null_check(receiver, T_OBJECT);
+  //should not do null check for argument for String.equals(), because spec
+  //allows to specify NULL as argument.
+  _sp -= 2;
+
+  if (stopped()) {
+    return true;
+  }
+
+  // get String klass for instanceOf
+  ciInstanceKlass* klass = env()->String_klass();
+
+  // two paths (plus control) merge
+  RegionNode* region = new (C, 3) RegionNode(3);
+  Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL);
+
+  Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
+  Node* cmp  = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1)));
+  Node* bol  = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq));
+
+  IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
+
+  Node* if_true  = _gvn.transform(new (C, 1) IfTrueNode(iff));
+  set_control(if_true);
+
+  const TypeInstPtr* string_type =
+    TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+
+  // instanceOf == true
+  Node* equals =
+    _gvn.transform(new (C, 7) StrEqualsNode(
+                        control(),
+                        memory(TypeAryPtr::CHARS),
+                        memory(string_type->add_offset(value_offset)),
+                        memory(string_type->add_offset(count_offset)),
+                        memory(string_type->add_offset(offset_offset)),
+                        receiver,
+                        argument));
+
+  phi->init_req(1, _gvn.transform(equals));
+  region->init_req(1, if_true);
+
+  //instanceOf == false, fallthrough
+  Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff));
+  set_control(if_false);
+
+  phi->init_req(2, _gvn.transform(intcon(0)));
+  region->init_req(2, if_false);
+
+  // post merge
+  set_control(_gvn.transform(region));
+  record_for_igvn(region);
+
+  push(_gvn.transform(phi));
+
+  return true;
+}
+
 //------------------------------inline_array_equals----------------------------
 bool LibraryCallKit::inline_array_equals() {
 
@@ -994,80 +1079,115 @@
   return result;
 }
 
-
 //------------------------------inline_string_indexOf------------------------
 bool LibraryCallKit::inline_string_indexOf() {
 
-  _sp += 2;
-  Node *argument = pop();  // pop non-receiver first:  it was pushed second
-  Node *receiver = pop();
-
-  // don't intrinsify if argument isn't a constant string.
-  if (!argument->is_Con()) {
-    return false;
-  }
-  const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr();
-  if (str_type == NULL) {
-    return false;
-  }
-  ciInstanceKlass* klass = env()->String_klass();
-  ciObject* str_const = str_type->const_oop();
-  if (str_const == NULL || str_const->klass() != klass) {
-    return false;
-  }
-  ciInstance* str = str_const->as_instance();
-  assert(str != NULL, "must be instance");
-
   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();
 
-  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();
-  ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
-
-  // 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()) {
-    return false;
-  }
-
-  // Null check on self without removing any arguments.  The argument
-  // null check technically happens in the wrong place, which can lead to
-  // invalid stack traces when string compare is inlined into a method
-  // which handles NullPointerExceptions.
   _sp += 2;
-  receiver = do_null_check(receiver, T_OBJECT);
-  // No null check on the argument is needed since it's a constant String oop.
-  _sp -= 2;
-  if (stopped()) {
-    return true;
+  Node *argument = pop();  // pop non-receiver first:  it was pushed second
+  Node *receiver = pop();
+
+  Node* result;
+  if (Matcher::has_match_rule(Op_StrIndexOf) &&
+      UseSSE42Intrinsics) {
+    // Generate SSE4.2 version of indexOf
+    // We currently only have match rules that use SSE4.2
+
+    // Null check on self without removing any arguments.  The argument
+    // null check technically happens in the wrong place, which can lead to
+    // invalid stack traces when string compare is inlined into a method
+    // which handles NullPointerExceptions.
+    _sp += 2;
+    receiver = do_null_check(receiver, T_OBJECT);
+    argument = do_null_check(argument, T_OBJECT);
+    _sp -= 2;
+
+    if (stopped()) {
+      return true;
+    }
+
+    ciInstanceKlass* klass = env()->String_klass();
+    const TypeInstPtr* string_type =
+      TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+
+    result =
+      _gvn.transform(new (C, 7)
+                     StrIndexOfNode(control(),
+                                    memory(TypeAryPtr::CHARS),
+                                    memory(string_type->add_offset(value_offset)),
+                                    memory(string_type->add_offset(count_offset)),
+                                    memory(string_type->add_offset(offset_offset)),
+                                    receiver,
+                                    argument));
+  } else { //Use LibraryCallKit::string_indexOf
+    // don't intrinsify is argument isn't a constant string.
+    if (!argument->is_Con()) {
+     return false;
+    }
+    const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr();
+    if (str_type == NULL) {
+      return false;
+    }
+    ciInstanceKlass* klass = env()->String_klass();
+    ciObject* str_const = str_type->const_oop();
+    if (str_const == NULL || str_const->klass() != klass) {
+      return false;
+    }
+    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();
+    ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
+
+    // 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()) {
+     return false;
+    }
+
+    // Null check on self without removing any arguments.  The argument
+    // null check technically happens in the wrong place, which can lead to
+    // invalid stack traces when string compare is inlined into a method
+    // which handles NullPointerExceptions.
+    _sp += 2;
+    receiver = do_null_check(receiver, T_OBJECT);
+    // No null check on the argument is needed since it's a constant String oop.
+    _sp -= 2;
+    if (stopped()) {
+     return true;
+    }
+
+    // The null string as a pattern always returns 0 (match at beginning of string)
+    if (c == 0) {
+      push(intcon(0));
+      return true;
+    }
+
+    // Generate default indexOf
+    jchar lastChar = pat->char_at(o + (c - 1));
+    int cache = 0;
+    int i;
+    for (i = 0; i < c - 1; i++) {
+      assert(i < pat->length(), "out of range");
+      cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
+    }
+
+    int md2 = c;
+    for (i = 0; i < c - 1; i++) {
+      assert(i < pat->length(), "out of range");
+      if (pat->char_at(o + i) == lastChar) {
+        md2 = (c - 1) - i;
+      }
+    }
+
+    result = string_indexOf(receiver, pat, o, cache, md2);
   }
 
-  // The null string as a pattern always returns 0 (match at beginning of string)
-  if (c == 0) {
-    push(intcon(0));
-    return true;
-  }
-
-  jchar lastChar = pat->char_at(o + (c - 1));
-  int cache = 0;
-  int i;
-  for (i = 0; i < c - 1; i++) {
-    assert(i < pat->length(), "out of range");
-    cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
-  }
-
-  int md2 = c;
-  for (i = 0; i < c - 1; i++) {
-    assert(i < pat->length(), "out of range");
-    if (pat->char_at(o + i) == lastChar) {
-      md2 = (c - 1) - i;
-    }
-  }
-
-  Node* result = string_indexOf(receiver, pat, o, cache, md2);
   push(result);
   return true;
 }
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -2668,6 +2668,8 @@
     case Op_LoadD_unaligned:
     case Op_LoadL_unaligned:
     case Op_StrComp:            // Does a bunch of load-like effects
+    case Op_StrEquals:
+    case Op_StrIndexOf:
     case Op_AryEq:
       pinned = false;
     }
--- a/hotspot/src/share/vm/opto/machnode.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/machnode.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -340,6 +340,10 @@
   if (base == NodeSentinel)  return TypePtr::BOTTOM;
 
   const Type* t = base->bottom_type();
+  if (UseCompressedOops && Universe::narrow_oop_shift() == 0) {
+    // 32-bit unscaled narrow oop can be the base of any address expression
+    t = t->make_ptr();
+  }
   if (t->isa_intptr_t() && offset != 0 && offset != Type::OffsetBot) {
     // We cannot assert that the offset does not look oop-ish here.
     // Depending on the heap layout the cardmark base could land
@@ -353,6 +357,7 @@
 
   // be conservative if we do not recognize the type
   if (tp == NULL) {
+    assert(false, "this path may produce not optimal code");
     return TypePtr::BOTTOM;
   }
   assert(tp->base() != Type::AnyPtr, "not a bare pointer");
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -746,6 +746,8 @@
   if (nidx == Compile::AliasIdxBot && midx == Compile::AliasIdxTop) {
     switch (n->Opcode()) {
     case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf:
     case Op_AryEq:
     case Op_MemBarVolatile:
     case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type?
@@ -1788,6 +1790,8 @@
         mstack.push(n->in(0), Pre_Visit);     // Visit Control input
         continue;                             // while (mstack.is_nonempty())
       case Op_StrComp:
+      case Op_StrEquals:
+      case Op_StrIndexOf:
       case Op_AryEq:
         set_shared(n); // Force result into register (it will be anyways)
         break;
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -2481,6 +2481,31 @@
   return remove_dead_region(phase, can_reshape) ? this : NULL;
 }
 
+// Do we match on this edge? No memory edges
+uint StrEqualsNode::match_edge(uint idx) const {
+  return idx == 5 || idx == 6;
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *StrEqualsNode::Ideal(PhaseGVN *phase, bool can_reshape){
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
+//=============================================================================
+// Do we match on this edge? No memory edges
+uint StrIndexOfNode::match_edge(uint idx) const {
+  return idx == 5 || idx == 6;
+}
+
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *StrIndexOfNode::Ideal(PhaseGVN *phase, bool can_reshape){
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
@@ -2488,7 +2513,6 @@
   return remove_dead_region(phase, can_reshape) ? this : NULL;
 }
 
-
 //=============================================================================
 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent)
   : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)),
--- a/hotspot/src/share/vm/opto/memnode.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -765,6 +765,54 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 };
 
+//------------------------------StrEquals-------------------------------------
+class StrEqualsNode: public Node {
+public:
+  StrEqualsNode(Node *control,
+                Node* char_array_mem,
+                Node* value_mem,
+                Node* count_mem,
+                Node* offset_mem,
+                Node* s1, Node* s2): Node(control,
+                                          char_array_mem,
+                                          value_mem,
+                                          count_mem,
+                                          offset_mem,
+                                          s1, s2) {};
+  virtual int Opcode() const;
+  virtual bool depends_only_on_test() const { return false; }
+  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
+  // a StrEqualsNode (conservatively) aliases with everything:
+  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
+  virtual uint match_edge(uint idx) const;
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+//------------------------------StrIndexOf-------------------------------------
+class StrIndexOfNode: public Node {
+public:
+  StrIndexOfNode(Node *control,
+                 Node* char_array_mem,
+                 Node* value_mem,
+                 Node* count_mem,
+                 Node* offset_mem,
+                 Node* s1, Node* s2): Node(control,
+                                           char_array_mem,
+                                           value_mem,
+                                           count_mem,
+                                           offset_mem,
+                                           s1, s2) {};
+  virtual int Opcode() const;
+  virtual bool depends_only_on_test() const { return false; }
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+  // a StrIndexOfNode (conservatively) aliases with everything:
+  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
+  virtual uint match_edge(uint idx) const;
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
 //------------------------------AryEq---------------------------------------
 class AryEqNode: public Node {
 public:
--- a/hotspot/src/share/vm/opto/parse1.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -95,7 +95,7 @@
   switch( bt ) {                // Signature is flattened
   case T_INT:     l = new (C, 3) LoadINode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
   case T_FLOAT:   l = new (C, 3) LoadFNode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
-  case T_ADDRESS:
+  case T_ADDRESS: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM  ); break;
   case T_OBJECT:  l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
   case T_LONG:
   case T_DOUBLE: {
--- a/hotspot/src/share/vm/opto/subnode.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -639,8 +639,8 @@
     int kps = (p0->isa_klassptr()?1:0) + (p1->isa_klassptr()?1:0);
     if (klass0 && klass1 &&
         kps != 1 &&             // both or neither are klass pointers
-        !klass0->is_interface() && // do not trust interfaces
-        !klass1->is_interface()) {
+        klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces
+        klass1->is_loaded() && !klass1->is_interface()) {
       bool unrelated_classes = false;
       // See if neither subclasses the other, or if the class on top
       // is precise.  In either of these cases, the compare is known
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -454,9 +454,13 @@
           // or need to run igvn.optimize() again before SLP
         } else if (out->is_Phi() && out->bottom_type() == Type::MEMORY && !in_bb(out)) {
           // Ditto.  Not sure what else to check further.
-        } else if (out->Opcode() == Op_StoreCM && out->in(4) == n) {
+        } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) {
           // StoreCM has an input edge used as a precedence edge.
           // Maybe an issue when oop stores are vectorized.
+        } else if( out->is_MergeMem() && prev &&
+                   prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) {
+          // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion
+          // for this case because it could not be superwordized anyway.
         } else {
           assert(out == prev || prev == NULL, "no branches off of store slice");
         }
@@ -912,54 +916,175 @@
   }
 }
 
-//------------------------------co_locate_pack---------------------------
-// Within a pack, move stores down to the last executed store,
-// and move loads up to the first executed load.
+//-------------------------------remove_and_insert-------------------
+//remove "current" from its current position in the memory graph and insert
+//it after the appropriate insertion point (lip or uip)
+void SuperWord::remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip,
+                                  Node *uip, Unique_Node_List &sched_before) {
+  Node* my_mem = current->in(MemNode::Memory);
+  _igvn.hash_delete(current);
+  _igvn.hash_delete(my_mem);
+
+  //remove current_store from its current position in the memmory graph
+  for (DUIterator i = current->outs(); current->has_out(i); i++) {
+    Node* use = current->out(i);
+    if (use->is_Mem()) {
+      assert(use->in(MemNode::Memory) == current, "must be");
+      _igvn.hash_delete(use);
+      if (use == prev) { // connect prev to my_mem
+        use->set_req(MemNode::Memory, my_mem);
+      } else if (sched_before.member(use)) {
+        _igvn.hash_delete(uip);
+        use->set_req(MemNode::Memory, uip);
+      } else {
+        _igvn.hash_delete(lip);
+        use->set_req(MemNode::Memory, lip);
+      }
+      _igvn._worklist.push(use);
+      --i; //deleted this edge; rescan position
+    }
+  }
+
+  bool sched_up = sched_before.member(current);
+  Node *insert_pt =  sched_up ?  uip : lip;
+  _igvn.hash_delete(insert_pt);
+
+  // all uses of insert_pt's memory state should use current's instead
+  for (DUIterator i = insert_pt->outs(); insert_pt->has_out(i); i++) {
+    Node* use = insert_pt->out(i);
+    if (use->is_Mem()) {
+      assert(use->in(MemNode::Memory) == insert_pt, "must be");
+      _igvn.hash_delete(use);
+      use->set_req(MemNode::Memory, current);
+      _igvn._worklist.push(use);
+      --i; //deleted this edge; rescan position
+    } else if (!sched_up && use->is_Phi() && use->bottom_type() == Type::MEMORY) {
+      uint pos; //lip (lower insert point) must be the last one in the memory slice
+      _igvn.hash_delete(use);
+      for (pos=1; pos < use->req(); pos++) {
+        if (use->in(pos) == insert_pt) break;
+      }
+      use->set_req(pos, current);
+      _igvn._worklist.push(use);
+      --i;
+    }
+  }
+
+  //connect current to insert_pt
+  current->set_req(MemNode::Memory, insert_pt);
+  _igvn._worklist.push(current);
+}
+
+//------------------------------co_locate_pack----------------------------------
+// To schedule a store pack, we need to move any sandwiched memory ops either before
+// or after the pack, based upon dependence information:
+// (1) If any store in the pack depends on the sandwiched memory op, the
+//     sandwiched memory op must be scheduled BEFORE the pack;
+// (2) If a sandwiched memory op depends on any store in the pack, the
+//     sandwiched memory op must be scheduled AFTER the pack;
+// (3) If a sandwiched memory op (say, memA) depends on another sandwiched
+//     memory op (say memB), memB must be scheduled before memA. So, if memA is
+//     scheduled before the pack, memB must also be scheduled before the pack;
+// (4) If there is no dependence restriction for a sandwiched memory op, we simply
+//     schedule this store AFTER the pack
+// (5) We know there is no dependence cycle, so there in no other case;
+// (6) Finally, all memory ops in another single pack should be moved in the same direction.
+//
+// To schedule a load pack: the memory edge of every loads in the pack must be
+// the same as the memory edge of the last executed load in the pack
 void SuperWord::co_locate_pack(Node_List* pk) {
   if (pk->at(0)->is_Store()) {
-    // Push Stores down towards last executed pack member
     MemNode* first     = executed_first(pk)->as_Mem();
     MemNode* last      = executed_last(pk)->as_Mem();
-    MemNode* insert_pt = last;
+    Unique_Node_List schedule_before_pack;
+    Unique_Node_List memops;
+
     MemNode* current   = last->in(MemNode::Memory)->as_Mem();
+    MemNode* previous  = last;
     while (true) {
       assert(in_bb(current), "stay in block");
+      memops.push(previous);
+      for (DUIterator i = current->outs(); current->has_out(i); i++) {
+        Node* use = current->out(i);
+        if (use->is_Mem() && use != previous)
+          memops.push(use);
+      }
+      if(current == first) break;
+      previous = current;
+      current  = current->in(MemNode::Memory)->as_Mem();
+    }
+
+    // determine which memory operations should be scheduled before the pack
+    for (uint i = 1; i < memops.size(); i++) {
+      Node *s1 = memops.at(i);
+      if (!in_pack(s1, pk) && !schedule_before_pack.member(s1)) {
+        for (uint j = 0; j< i; j++) {
+          Node *s2 = memops.at(j);
+          if (!independent(s1, s2)) {
+            if (in_pack(s2, pk) || schedule_before_pack.member(s2)) {
+              schedule_before_pack.push(s1); //s1 must be scheduled before
+              Node_List* mem_pk = my_pack(s1);
+              if (mem_pk != NULL) {
+                for (uint ii = 0; ii < mem_pk->size(); ii++) {
+                  Node* s = mem_pk->at(ii); // follow partner
+                  if (memops.member(s) && !schedule_before_pack.member(s))
+                    schedule_before_pack.push(s);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    MemNode* lower_insert_pt = last;
+    Node*    upper_insert_pt = first->in(MemNode::Memory);
+    previous                 = last; //previous store in pk
+    current                  = last->in(MemNode::Memory)->as_Mem();
+
+    //start scheduling from "last" to "first"
+    while (true) {
+      assert(in_bb(current), "stay in block");
+      assert(in_pack(previous, pk), "previous stays in pack");
       Node* my_mem = current->in(MemNode::Memory);
+
       if (in_pack(current, pk)) {
-        // Forward users of my memory state to my input memory state
+        // Forward users of my memory state (except "previous) to my input memory state
         _igvn.hash_delete(current);
-        _igvn.hash_delete(my_mem);
         for (DUIterator i = current->outs(); current->has_out(i); i++) {
           Node* use = current->out(i);
-          if (use->is_Mem()) {
+          if (use->is_Mem() && use != previous) {
             assert(use->in(MemNode::Memory) == current, "must be");
             _igvn.hash_delete(use);
-            use->set_req(MemNode::Memory, my_mem);
+            if (schedule_before_pack.member(use)) {
+              _igvn.hash_delete(upper_insert_pt);
+              use->set_req(MemNode::Memory, upper_insert_pt);
+            } else {
+              _igvn.hash_delete(lower_insert_pt);
+              use->set_req(MemNode::Memory, lower_insert_pt);
+            }
             _igvn._worklist.push(use);
             --i; // deleted this edge; rescan position
           }
         }
-        // put current immediately before insert_pt
-        current->set_req(MemNode::Memory, insert_pt->in(MemNode::Memory));
-        _igvn.hash_delete(insert_pt);
-        insert_pt->set_req(MemNode::Memory, current);
-        _igvn._worklist.push(insert_pt);
-        _igvn._worklist.push(current);
-        insert_pt = current;
+        previous = current;
+      } else { // !in_pack(current, pk) ==> a sandwiched store
+        remove_and_insert(current, previous, lower_insert_pt, upper_insert_pt, schedule_before_pack);
       }
+
       if (current == first) break;
       current = my_mem->as_Mem();
-    }
-  } else if (pk->at(0)->is_Load()) {
-    // Pull Loads up towards first executed pack member
-    LoadNode* first = executed_first(pk)->as_Load();
-    Node* first_mem = first->in(MemNode::Memory);
-    _igvn.hash_delete(first_mem);
-    // Give each load same memory state as first
+    } // end while
+  } else if (pk->at(0)->is_Load()) { //load
+    // all use the memory state that the last executed load uses
+    LoadNode* last_load  = executed_last(pk)->as_Load();
+    Node* last_mem       = last_load->in(MemNode::Memory);
+    _igvn.hash_delete(last_mem);
+    // Give each load same memory state as last
     for (uint i = 0; i < pk->size(); i++) {
       LoadNode* ld = pk->at(i)->as_Load();
       _igvn.hash_delete(ld);
-      ld->set_req(MemNode::Memory, first_mem);
+      ld->set_req(MemNode::Memory, last_mem);
       _igvn._worklist.push(ld);
     }
   }
--- a/hotspot/src/share/vm/opto/superword.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -341,8 +341,11 @@
   void filter_packs();
   // Adjust the memory graph for the packed operations
   void schedule();
-  // Within a pack, move stores down to the last executed store,
-  // and move loads up to the first executed load.
+  // Remove "current" from its current position in the memory graph and insert
+  // it after the appropriate insert points (lip or uip);
+  void remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, Node *uip, Unique_Node_List &schd_before);
+  // Within a store pack, schedule stores together by moving out the sandwiched memory ops according
+  // to dependence info; and within a load pack, move loads down to the last executed load.
   void co_locate_pack(Node_List* p);
   // Convert packs into vector node operations
   void output();
--- a/hotspot/src/share/vm/prims/jvm.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1252,7 +1252,7 @@
 
            // Throws an exception if outer klass has not declared k as
            // an inner klass
-           Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL);
+           Reflection::check_for_inner_class(k, inner_klass, true, CHECK_NULL);
 
            result->obj_at_put(members, inner_klass->java_mirror());
            members++;
@@ -1275,16 +1275,29 @@
 
 
 JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass))
-  const int inner_class_info_index = 0;
-  const int outer_class_info_index = 1;
-
+{
   // ofClass is a reference to a java_lang_Class object.
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
       ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) {
     return NULL;
   }
 
-  instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
+  symbolOop simple_name = NULL;
+  klassOop outer_klass
+    = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))
+                          )->compute_enclosing_class(simple_name, CHECK_NULL);
+  if (outer_klass == NULL)  return NULL;  // already a top-level class
+  if (simple_name == NULL)  return NULL;  // an anonymous class (inside a method)
+  return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror());
+}
+JVM_END
+
+// should be in instanceKlass.cpp, but is here for historical reasons
+klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k,
+                                                     symbolOop& simple_name_result, TRAPS) {
+  Thread* thread = THREAD;
+  const int inner_class_info_index = inner_class_inner_class_info_offset;
+  const int outer_class_info_index = inner_class_outer_class_info_offset;
 
   if (k->inner_classes()->length() == 0) {
     // No inner class info => no declaring class
@@ -1298,35 +1311,51 @@
   bool found = false;
   klassOop ok;
   instanceKlassHandle outer_klass;
+  bool inner_is_member = false;
+  int simple_name_index = 0;
 
   // Find inner_klass attribute
-  for(int i = 0; i < i_length && !found; i+= 4) {
+  for (int i = 0; i < i_length && !found; i += inner_class_next_offset) {
     int ioff = i_icls->ushort_at(i + inner_class_info_index);
     int ooff = i_icls->ushort_at(i + outer_class_info_index);
-
-    if (ioff != 0 && ooff != 0) {
+    int noff = i_icls->ushort_at(i + inner_class_inner_name_offset);
+    if (ioff != 0) {
       // Check to see if the name matches the class we're looking for
       // before attempting to find the class.
       if (i_cp->klass_name_at_matches(k, ioff)) {
         klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL);
-        if (k() == inner_klass) {
-          found = true;
+        found = (k() == inner_klass);
+        if (found && ooff != 0) {
           ok = i_cp->klass_at(ooff, CHECK_NULL);
           outer_klass = instanceKlassHandle(thread, ok);
+          simple_name_index = noff;
+          inner_is_member = true;
         }
       }
     }
   }
 
+  if (found && outer_klass.is_null()) {
+    // It may be anonymous; try for that.
+    int encl_method_class_idx = k->enclosing_method_class_index();
+    if (encl_method_class_idx != 0) {
+      ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
+      outer_klass = instanceKlassHandle(thread, ok);
+      inner_is_member = false;
+    }
+  }
+
   // If no inner class attribute found for this class.
-  if (!found) return NULL;
+  if (outer_klass.is_null())  return NULL;
 
   // Throws an exception if outer klass has not declared k as an inner klass
-  Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL);
-
-  return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror());
-JVM_END
-
+  // We need evidence that each klass knows about the other, or else
+  // the system could allow a spoof of an inner class to gain access rights.
+  Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL);
+
+  simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL));
+  return outer_klass();
+}
 
 JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls))
   assert (cls != NULL, "illegal class");
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -852,16 +852,13 @@
       FreeHeap(value);
     }
     return true;
-  }
-  else if (strcmp(key, "sun.java.command") == 0) {
-
+  } else if (strcmp(key, "sun.java.command") == 0) {
     _java_command = value;
 
     // don't add this property to the properties exposed to the java application
     FreeHeap(key);
     return true;
-  }
-  else if (strcmp(key, "sun.java.launcher.pid") == 0) {
+  } else if (strcmp(key, "sun.java.launcher.pid") == 0) {
     // launcher.pid property is private and is processed
     // in process_sun_java_launcher_properties();
     // the sun.java.launcher property is passed on to the java application
@@ -870,13 +867,14 @@
       FreeHeap(value);
     }
     return true;
-  }
-  else if (strcmp(key, "java.vendor.url.bug") == 0) {
+  } else if (strcmp(key, "java.vendor.url.bug") == 0) {
     // save it in _java_vendor_url_bug, so JVM fatal error handler can access
     // its value without going through the property list or making a Java call.
     _java_vendor_url_bug = value;
+  } else if (strcmp(key, "sun.boot.library.path") == 0) {
+    PropertyList_unique_add(&_system_properties, key, value, true);
+    return true;
   }
-
   // Create new property and add at the end of the list
   PropertyList_unique_add(&_system_properties, key, value);
   return true;
@@ -895,7 +893,7 @@
   // Ensure Agent_OnLoad has the correct initial values.
   // This may not be the final mode; mode may change later in onload phase.
   PropertyList_unique_add(&_system_properties, "java.vm.info",
-     (char*)Abstract_VM_Version::vm_info_string());
+                          (char*)Abstract_VM_Version::vm_info_string(), false);
 
   UseInterpreter             = true;
   UseCompiler                = true;
@@ -971,7 +969,7 @@
   } else {
     no_shared_spaces();
 
-    // By default YoungPLABSize and OldPLABSize are set to 4096 and 1024 correspondinly,
+    // By default YoungPLABSize and OldPLABSize are set to 4096 and 1024 respectively,
     // these settings are default for Parallel Scavenger. For ParNew+Tenured configuration
     // we set them to 1024 and 1024.
     // See CR 6362902.
@@ -987,6 +985,16 @@
     if (AlwaysTenure) {
       FLAG_SET_CMDLINE(intx, MaxTenuringThreshold, 0);
     }
+    // When using compressed oops, we use local overflow stacks,
+    // rather than using a global overflow list chained through
+    // the klass word of the object's pre-image.
+    if (UseCompressedOops && !ParGCUseLocalOverflow) {
+      if (!FLAG_IS_DEFAULT(ParGCUseLocalOverflow)) {
+        warning("Forcing +ParGCUseLocalOverflow: needed if using compressed references");
+      }
+      FLAG_SET_DEFAULT(ParGCUseLocalOverflow, true);
+    }
+    assert(ParGCUseLocalOverflow || !UseCompressedOops, "Error");
   }
 }
 
@@ -1366,9 +1374,6 @@
   if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
     FLAG_SET_DEFAULT(DoEscapeAnalysis, true);
   }
-  if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) {
-    FLAG_SET_DEFAULT(SpecialArraysEquals, true);
-  }
   if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
     FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
   }
@@ -2767,7 +2772,7 @@
 }
 
 // This add maintains unique property key in the list.
-void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) {
+void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append) {
   if (plist == NULL)
     return;
 
@@ -2775,7 +2780,11 @@
   SystemProperty* prop;
   for (prop = *plist; prop != NULL; prop = prop->next()) {
     if (strcmp(k, prop->key()) == 0) {
-      prop->set_value(v);
+      if (append) {
+        prop->append_value(v);
+      } else {
+        prop->set_value(v);
+      }
       return;
     }
   }
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -475,10 +475,13 @@
   // System properties
   static void init_system_properties();
 
-  // Proptery List manipulation
+  // Property List manipulation
   static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
   static void PropertyList_add(SystemProperty** plist, const char* k, char* v);
-  static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v);
+  static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) {
+    PropertyList_unique_add(plist, k, v, false);
+  }
+  static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append);
   static const char* PropertyList_get_value(SystemProperty* plist, const char* key);
   static int  PropertyList_count(SystemProperty* pl);
   static const char* PropertyList_get_key_at(SystemProperty* pl,int index);
--- a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,13 +107,14 @@
 void fieldDescriptor::print_on_for(outputStream* st, oop obj) {
   print_on(st);
   BasicType ft = field_type();
-  jint as_int;
+  jint as_int = 0;
   switch (ft) {
     case T_BYTE:
       as_int = (jint)obj->byte_field(offset());
       st->print(" %d", obj->byte_field(offset()));
       break;
     case T_CHAR:
+      as_int = (jint)obj->char_field(offset());
       {
         jchar c = obj->char_field(offset());
         as_int = c;
@@ -128,6 +129,7 @@
       st->print(" %f", obj->float_field(offset()));
       break;
     case T_INT:
+      as_int = obj->int_field(offset());
       st->print(" %d", obj->int_field(offset()));
       break;
     case T_LONG:
@@ -144,12 +146,12 @@
       break;
     case T_ARRAY:
       st->print(" ");
-      as_int = obj->int_field(offset());
+      NOT_LP64(as_int = obj->int_field(offset()));
       obj->obj_field(offset())->print_value_on(st);
       break;
     case T_OBJECT:
       st->print(" ");
-      as_int = obj->int_field(offset());
+      NOT_LP64(as_int = obj->int_field(offset()));
       obj->obj_field(offset())->print_value_on(st);
       break;
     default:
@@ -158,9 +160,9 @@
   }
   // Print a hint as to the underlying integer representation. This can be wrong for
   // pointers on an LP64 machine
-  if (ft == T_LONG || ft == T_DOUBLE) {
+  if (ft == T_LONG || ft == T_DOUBLE LP64_ONLY(|| !is_java_primitive(ft)) ) {
     st->print(" (%x %x)", obj->int_field(offset()), obj->int_field(offset()+sizeof(jint)));
-  } else {
+  } else if (as_int < 0 || as_int > 9) {
     st->print(" (%x)", as_int);
   }
 }
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -47,6 +47,7 @@
 define_pd_global(intx, OnStackReplacePercentage,     0);
 define_pd_global(bool, ResizeTLAB,                   false);
 define_pd_global(intx, FreqInlineSize,               0);
+define_pd_global(intx, InlineSmallCode,              0);
 define_pd_global(intx, NewSizeThreadIncrease,        4*K);
 define_pd_global(intx, NewRatio,                     4);
 define_pd_global(intx, InlineClassNatives,           true);
@@ -490,9 +491,15 @@
   develop(bool, SpecialStringIndexOf, true,                                 \
           "special version of string indexOf")                              \
                                                                             \
-  product(bool, SpecialArraysEquals, false,                                 \
+  develop(bool, SpecialStringEquals, true,                                  \
+          "special version of string equals")                               \
+                                                                            \
+  develop(bool, SpecialArraysEquals, true,                                  \
           "special version of Arrays.equals(char[],char[])")                \
                                                                             \
+  product(bool, UseSSE42Intrinsics, false,                                  \
+          "SSE4.2 versions of intrinsics")                                  \
+                                                                            \
   develop(bool, TraceCallFixup, false,                                      \
           "traces all call fixups")                                         \
                                                                             \
@@ -1316,6 +1323,12 @@
   product(intx, ParGCArrayScanChunk, 50,                                    \
           "Scan a subset and push remainder, if array is bigger than this") \
                                                                             \
+  product(bool, ParGCUseLocalOverflow, false,                               \
+          "Instead of a global overflow list, use local overflow stacks")   \
+                                                                            \
+  product(bool, ParGCTrimOverflow, true,                                    \
+          "Eagerly trim the local overflow lists (when ParGCUseLocalOverflow") \
+                                                                            \
   notproduct(bool, ParGCWorkQueueOverflowALot, false,                       \
           "Whether we should simulate work queue overflow in ParNew")       \
                                                                             \
@@ -2616,7 +2629,7 @@
   develop(intx, MaxRecursiveInlineLevel, 1,                                 \
           "maximum number of nested recursive calls that are inlined")      \
                                                                             \
-  product(intx, InlineSmallCode, 1000,                                      \
+  product_pd(intx, InlineSmallCode,                                         \
           "Only inline already compiled methods if their code size is "     \
           "less than this")                                                 \
                                                                             \
--- a/hotspot/src/share/vm/runtime/handles.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/handles.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,6 +137,14 @@
     assert(is_null() || obj()->is_klass(), "not a klassOop");
   }
 
+  // Direct interface, use very sparingly.
+  // Used by SystemDictionaryHandles to create handles on existing WKKs.
+  // The obj of such a klass handle may be null, because the handle is formed
+  // during system bootstrapping.
+  KlassHandle(klassOop *handle, bool dummy) : Handle((oop*)handle, dummy) {
+    assert(SharedSkipVerify || is_null() || obj() == NULL || obj()->is_klass(), "not a klassOop");
+  }
+
   // General access
   klassOop    operator () () const               { return obj(); }
   Klass*      operator -> () const               { return as_klass(); }
--- a/hotspot/src/share/vm/runtime/hpi.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/hpi.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -90,7 +90,7 @@
   static inline struct protoent* get_proto_by_name(char* name);
 
   // HPI_LibraryInterface
-  static inline void   dll_build_name(char *buf, int buf_len, char* path,
+  static inline void   dll_build_name(char *buf, int buf_len, const char* path,
                                       const char *name);
   static inline void*  dll_load(const char *name, char *ebuf, int ebuflen);
   static inline void   dll_unload(void *lib);
@@ -137,7 +137,15 @@
     return result;                            \
   }
 
-
+#define VM_HPIDECL_VOID(name, names, func, arg_type, arg_print, arg)   \
+  inline void  hpi::name arg_type {           \
+    if (TraceHPI) {                           \
+      tty->print("hpi::" names "(");          \
+      tty->print arg_print;                   \
+      tty->print(") = ");                     \
+    }                                         \
+    func arg;                                 \
+  }
 
 #define HPIDECL_VOID(name, names, intf, func, arg_type, arg_print, arg) \
   inline void hpi::name arg_type {            \
@@ -197,11 +205,11 @@
         (fd, size));
 
 // HPI_LibraryInterface
-HPIDECL_VOID(dll_build_name, "dll_build_name", _library, BuildLibName,
-             (char *buf, int buf_len, char *path, const char *name),
-             ("buf = %p, buflen = %d, path = %s, name = %s",
-              buf, buf_len, path, name),
-             (buf, buf_len, path, name));
+VM_HPIDECL_VOID(dll_build_name, "dll_build_name", os::dll_build_name,
+               (char *buf, int buf_len, const char *path, const char *name),
+               ("buf = %p, buflen = %d, path = %s, name = %s",
+                buf, buf_len, path, name),
+               (buf, buf_len, path, name));
 
 VM_HPIDECL(dll_load, "dll_load", os::dll_load,
         void *, "(void *)%p",
--- a/hotspot/src/share/vm/runtime/orderAccess.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/orderAccess.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -26,3 +26,15 @@
 # include "incls/_orderAccess.cpp.incl"
 
 volatile intptr_t OrderAccess::dummy = 0;
+
+void OrderAccess::StubRoutines_fence() {
+  // Use a stub if it exists.  It may not exist during bootstrap so do
+  // nothing in that case but assert if no fence code exists after threads have been created
+  void (*func)() = CAST_TO_FN_PTR(void (*)(), StubRoutines::fence_entry());
+
+  if (func != NULL) {
+    (*func)();
+    return;
+  }
+  assert(Threads::number_of_threads() == 0, "for bootstrap only");
+}
--- a/hotspot/src/share/vm/runtime/orderAccess.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/orderAccess.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -300,4 +300,10 @@
   // In order to force a memory access, implementations may
   // need a volatile externally visible dummy variable.
   static volatile intptr_t dummy;
+
+ private:
+  // This is a helper that invokes the StubRoutines::fence_entry()
+  // routine if it exists, It should only be used by platforms that
+  // don't another way to do the inline eassembly.
+  static void StubRoutines_fence();
 };
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -863,7 +863,6 @@
 
 
 bool os::set_boot_path(char fileSep, char pathSep) {
-
     const char* home = Arguments::get_java_home();
     int home_len = (int)strlen(home);
 
@@ -893,6 +892,60 @@
     return true;
 }
 
+/*
+ * Splits a path, based on its separator, the number of
+ * elements is returned back in n.
+ * It is the callers responsibility to:
+ *   a> check the value of n, and n may be 0.
+ *   b> ignore any empty path elements
+ *   c> free up the data.
+ */
+char** os::split_path(const char* path, int* n) {
+  *n = 0;
+  if (path == NULL || strlen(path) == 0) {
+    return NULL;
+  }
+  const char psepchar = *os::path_separator();
+  char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1);
+  if (inpath == NULL) {
+    return NULL;
+  }
+  strncpy(inpath, path, strlen(path));
+  int count = 1;
+  char* p = strchr(inpath, psepchar);
+  // Get a count of elements to allocate memory
+  while (p != NULL) {
+    count++;
+    p++;
+    p = strchr(p, psepchar);
+  }
+  char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count);
+  if (opath == NULL) {
+    return NULL;
+  }
+
+  // do the actual splitting
+  p = inpath;
+  for (int i = 0 ; i < count ; i++) {
+    size_t len = strcspn(p, os::path_separator());
+    if (len > JVM_MAXPATHLEN) {
+      return NULL;
+    }
+    // allocate the string and add terminator storage
+    char* s  = (char*)NEW_C_HEAP_ARRAY(char, len + 1);
+    if (s == NULL) {
+      return NULL;
+    }
+    strncpy(s, p, len);
+    s[len] = '\0';
+    opath[i] = s;
+    p += len + 1;
+  }
+  FREE_C_HEAP_ARRAY(char, inpath);
+  *n = count;
+  return opath;
+}
+
 void os::set_memory_serialize_page(address page) {
   int count = log2_intptr(sizeof(class JavaThread)) - log2_intptr(64);
   _mem_serialize_page = (volatile int32_t *)page;
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -607,6 +607,7 @@
                                 char fileSep,
                                 char pathSep);
   static bool set_boot_path(char fileSep, char pathSep);
+  static char** split_path(const char* path, int* n);
 };
 
 // Note that "PAUSE" is almost always used with synchronization
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -554,10 +554,18 @@
   return instanceKlass::cast(class1)->is_same_class_package(class2);
 }
 
+bool Reflection::is_same_package_member(klassOop class1, klassOop class2, TRAPS) {
+  return instanceKlass::cast(class1)->is_same_package_member(class2, THREAD);
+}
+
 
 // Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not,
 // throw an incompatible class change exception
-void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS) {
+// If inner_is_member, require the inner to be a member of the outer.
+// If !inner_is_member, require the inner to be anonymous (a non-member).
+// Caller is responsible for figuring out in advance which case must be true.
+void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
+                                       bool inner_is_member, TRAPS) {
   const int inner_class_info_index = 0;
   const int outer_class_info_index = 1;
 
@@ -567,7 +575,7 @@
      int ioff = icls->ushort_at(i + inner_class_info_index);
      int ooff = icls->ushort_at(i + outer_class_info_index);
 
-     if (ioff != 0 && ooff != 0) {
+     if (inner_is_member && ioff != 0 && ooff != 0) {
         klassOop o = cp->klass_at(ooff, CHECK);
         if (o == outer()) {
           klassOop i = cp->klass_at(ioff, CHECK);
@@ -576,6 +584,13 @@
           }
         }
      }
+     if (!inner_is_member && ioff != 0 && ooff == 0 &&
+         cp->klass_name_at_matches(inner, ioff)) {
+        klassOop i = cp->klass_at(ioff, CHECK);
+        if (i == inner()) {
+          return;
+        }
+     }
   }
 
   // 'inner' not declared as an inner klass in outer
--- a/hotspot/src/share/vm/runtime/reflection.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,12 +87,18 @@
                                       bool classloader_only,
                                       bool protected_restriction = false);
   static bool     is_same_class_package(klassOop class1, klassOop class2);
+  static bool     is_same_package_member(klassOop class1, klassOop class2, TRAPS);
 
   static bool can_relax_access_check_for(
     klassOop accessor, klassOop accesee, bool classloader_only);
 
   // inner class reflection
-  static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS);
+  // raise an ICCE unless the required relationship can be proven to hold
+  // If inner_is_member, require the inner to be a member of the outer.
+  // If !inner_is_member, require the inner to be anonymous (a non-member).
+  // Caller is responsible for figuring out in advance which case must be true.
+  static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
+                                    bool inner_is_member, TRAPS);
 
   //
   // Support for reflection based on dynamic bytecode generation (JDK 1.4)
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -675,48 +675,6 @@
 JRT_END
 
 
-// ---------------------------------------------------------------------------------------------------------
-// Non-product code
-#ifndef PRODUCT
-
-void SharedRuntime::verify_caller_frame(frame caller_frame, methodHandle callee_method) {
-  ResourceMark rm;
-  assert (caller_frame.is_interpreted_frame(), "sanity check");
-  assert (callee_method->has_compiled_code(), "callee must be compiled");
-  methodHandle caller_method (Thread::current(), caller_frame.interpreter_frame_method());
-  jint bci = caller_frame.interpreter_frame_bci();
-  methodHandle method = find_callee_method_inside_interpreter(caller_frame, caller_method, bci);
-  assert (callee_method == method, "incorrect method");
-}
-
-methodHandle SharedRuntime::find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) {
-  EXCEPTION_MARK;
-  Bytecode_invoke* bytecode = Bytecode_invoke_at(caller_method, bci);
-  methodHandle staticCallee = bytecode->static_target(CATCH); // Non-product code
-
-  bytecode = Bytecode_invoke_at(caller_method, bci);
-  int bytecode_index = bytecode->index();
-  Bytecodes::Code bc = bytecode->adjusted_invoke_code();
-
-  Handle receiver;
-  if (bc == Bytecodes::_invokeinterface ||
-      bc == Bytecodes::_invokevirtual ||
-      bc == Bytecodes::_invokespecial) {
-    symbolHandle signature (THREAD, staticCallee->signature());
-    receiver = Handle(THREAD, retrieve_receiver(signature, caller_frame));
-  } else {
-    receiver = Handle();
-  }
-  CallInfo result;
-  constantPoolHandle constants (THREAD, caller_method->constants());
-  LinkResolver::resolve_invoke(result, receiver, constants, bytecode_index, bc, CATCH); // Non-product code
-  methodHandle calleeMethod = result.selected_method();
-  return calleeMethod;
-}
-
-#endif  // PRODUCT
-
-
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
   assert(obj->is_oop(), "must be a valid oop");
   assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise");
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -180,9 +180,6 @@
 
   static oop retrieve_receiver( symbolHandle sig, frame caller );
 
-  static void verify_caller_frame(frame caller_frame, methodHandle callee_method) PRODUCT_RETURN;
-  static methodHandle find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) PRODUCT_RETURN_(return methodHandle(););
-
   static void register_finalizer(JavaThread* thread, oopDesc* obj);
 
   // dtrace notifications
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 16:50:32 2017 +0200
@@ -3007,17 +3007,19 @@
       }
 
       if (UseStringCache) {
-        // Forcibly initialize java/lang/String and mutate the private
+        // Forcibly initialize java/lang/StringValue and mutate the private
         // static final "stringCacheEnabled" field before we start creating instances
-        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0);
-        KlassHandle k = KlassHandle(THREAD, k_o);
-        guarantee(k.not_null(), "Must find java/lang/String");
-        instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
-        ik->initialize(CHECK_0);
-        fieldDescriptor fd;
-        // Possible we might not find this field; if so, don't break
-        if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
-          k()->bool_field_put(fd.offset(), true);
+        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
+        // Possible that StringValue isn't present: if so, silently don't break
+        if (k_o != NULL) {
+          KlassHandle k = KlassHandle(THREAD, k_o);
+          instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
+          ik->initialize(CHECK_0);
+          fieldDescriptor fd;
+          // Possible we might not find this field: if so, silently don't break
+          if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+            k()->bool_field_put(fd.offset(), true);
+          }
         }
       }
     }
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Thu Apr 02 16:51:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Jul 05 16:50:32 2017 +0200
@@ -59,7 +59,6 @@
   template(G1CollectFull)                         \
   template(G1CollectForAllocation)                \
   template(G1IncCollectionPause)                  \
-  template(G1PopRegionCollectionPause)            \
   template(EnableBiasedLocking)                   \
   template(RevokeBias)                            \
   template(BulkRevokeBias)                        \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6636138/Test1.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6636138
+ * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
+ *
+ * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init -XX:+UseSuperword Test1
+ */
+
+class Test1 {
+
+    public static void init(int src[], int [] dst, int[] ref) {
+        // initialize the arrays
+        for (int i =0; i<src.length; i++) {
+            src[i] =  i;
+            dst[i] = 2;      // yes, dst[i] needed(otherwise src[i] will be replaced with i)
+            ref[i] = src[i]; // src[i] depends on the store src[i]
+        }
+    }
+
+    public static void verify(int src[], int[] ref) {
+        // check whether src and ref are equal
+        for (int i = 0; i < src.length; i++) {
+            if (src[i] != ref[i]) {
+                System.out.println("Error: src and ref don't match at " + i);
+                System.exit(-1);
+            }
+        }
+    }
+
+    public static void test() {
+        int[] src = new int[34];
+        int[] dst = new int[34];
+        int[] ref = new int[34];
+
+        init(src, dst, ref);
+        verify(src, ref);
+    }
+
+    public static void main(String[] args) {
+        for (int i=0; i< 2000; i++) {
+            test();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6636138/Test2.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6636138
+ * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
+ *
+ * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift -XX:+UseSuperword Test2
+ */
+
+class Test2 {
+
+    public static void init(int src[]) {
+        // Initialize the array
+        for (int i = 0; i < src.length; i++)
+            src[i] = i;
+    }
+
+   public static void shift(int src[]) {
+       //left-shift the array
+       for (int i = src.length-1; i > 0; i--){
+           int tmp  = src[i];
+           src[i]   = src[i-1];
+           src[i-1] = tmp;
+       }
+    }
+
+    public static void verify(int src[]) {
+        for (int i = 0; i < src.length; i++){
+            int value = (i-1 + src.length)%src.length; // correct value after shifting
+                if (src[i] != value) {
+                    System.out.println("Error: src["+i+"] should be "+ value + " instead of " + src[i]);
+                    System.exit(-1);
+                }
+        }
+    }
+
+    public static void test() {
+        int[] src = new int[10];
+        init(src);
+        shift(src);
+        verify(src);
+    }
+
+    public static void main(String[] args) {
+        for (int i=0; i< 2000; i++)
+            test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/6819213/TestBootNativeLibraryPath.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test TestBootNativeLibraryPath.java
+ * @bug 6819213
+ * @compile -XDignore.symbol.file TestBootNativeLibraryPath.java
+ * @summary verify sun.boot.native.library.path is expandable on 32 bit systems
+ * @run main TestBootNativeLibraryPath
+ * @author ksrini
+*/
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+public class TestBootNativeLibraryPath {
+
+    private static final String TESTFILE = "Test6";
+
+    static void createTestClass() throws IOException {
+        FileOutputStream fos = new FileOutputStream(TESTFILE + ".java");
+        PrintStream ps = new PrintStream(fos);
+        ps.println("public class " + TESTFILE + "{");
+        ps.println("public static void main(String[] args) {\n");
+        ps.println("System.out.println(System.getProperty(\"sun.boot.library.path\"));\n");
+        ps.println("}}\n");
+        ps.close();
+        fos.close();
+
+        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+        String javacOpts[] = {TESTFILE + ".java"};
+        if (javac.run(null, null, null,  javacOpts) != 0) {
+            throw new RuntimeException("compilation of " + TESTFILE + ".java Failed");
+        }
+    }
+
+    static List<String> doExec(String... args) {
+        String javaCmd = System.getProperty("java.home") + "/bin/java";
+        if (!new File(javaCmd).exists()) {
+            javaCmd = System.getProperty("java.home") + "/bin/java.exe";
+        }
+
+        ArrayList<String> cmds = new ArrayList<String>();
+        cmds.add(javaCmd);
+        for (String x : args) {
+            cmds.add(x);
+        }
+        System.out.println("cmds=" + cmds);
+        ProcessBuilder pb = new ProcessBuilder(cmds);
+
+        Map<String, String> env = pb.environment();
+        pb.directory(new File("."));
+
+        List<String> out = new ArrayList<String>();
+        try {
+            pb.redirectErrorStream(true);
+            Process p = pb.start();
+            BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()),8192);
+            String in = rd.readLine();
+            while (in != null) {
+                out.add(in);
+                System.out.println(in);
+                in = rd.readLine();
+            }
+            int retval = p.waitFor();
+            p.destroy();
+            if (retval != 0) {
+                throw new RuntimeException("Error: test returned non-zero value");
+            }
+            return out;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    public static void main(String[] args) {
+        try {
+            if (!System.getProperty("sun.arch.data.model").equals("32")) {
+                System.out.println("Warning: test skipped for 64-bit systems\n");
+                return;
+            }
+            String osname = System.getProperty("os.name");
+            if (osname.startsWith("Windows")) {
+                osname = "Windows";
+            }
+
+            createTestClass();
+
+            // Test a simple path
+            String libpath = File.pathSeparator + "tmp" + File.pathSeparator + "foobar";
+            List<String> processOut = null;
+            String sunbootlibrarypath = "-Dsun.boot.library.path=" + libpath;
+            processOut = doExec(sunbootlibrarypath, "-cp", ".", TESTFILE);
+            if (processOut == null || !processOut.get(0).endsWith(libpath)) {
+                throw new RuntimeException("Error: did not get expected error string");
+            }
+        } catch (IOException ex) {
+            throw new RuntimeException("Unexpected error " + ex);
+        }
+    }
+}
--- a/jaxp/.hgtags	Thu Apr 02 16:51:48 2009 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 16:50:32 2017 +0200
@@ -27,3 +27,4 @@
 e8514e2be76d90889ebdb90d627aca2db5c150c6 jdk7-b50
 ae890d80d5dffcd4dc77a1f17d768e192d1852c7 jdk7-b51
 69ad87dc25cbcaaaded4727199395ad0c78bc427 jdk7-b52
+e8837366d3fd72f7c7a47ebfdbd5106c16156f12 jdk7-b53
--- a/jdk/.hgtags	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/.hgtags	Wed Jul 05 16:50:32 2017 +0200
@@ -27,3 +27,4 @@
 58ba2cd5a25053684ec53205d95edeeaa0006f13 jdk7-b50
 fea0898259ae41c73620b1815aa48f036216155c jdk7-b51
 bcbeadb4a5d759b29e876ee2c83401e91ff22f60 jdk7-b52
+a2033addca678f9e4c0d92ffa1e389171cc9321d jdk7-b53
--- a/jdk/make/common/Defs-linux.gmk	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/common/Defs-linux.gmk	Wed Jul 05 16:50:32 2017 +0200
@@ -94,6 +94,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 CC_OPT/NONE     = 
 CC_OPT/LOWER    = -O2
@@ -173,8 +176,8 @@
 
 # FASTDEBUG: Optimize the code in the -g versions, gives us a faster debug java
 ifeq ($(FASTDEBUG), true)
-  CFLAGS_DBG    += $(CC_OPT/LOWER)
-  CXXFLAGS_DBG	+= $(CC_OPT/LOWER)
+  CFLAGS_DBG    += $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
+  CXXFLAGS_DBG	+= $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
 endif
 
 CPPFLAGS_COMMON = -D$(ARCH) -DARCH='"$(ARCH)"' -DLINUX $(VERSION_DEFINES) \
--- a/jdk/make/common/Defs-solaris.gmk	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/common/Defs-solaris.gmk	Wed Jul 05 16:50:32 2017 +0200
@@ -93,6 +93,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 #
 # If -Xa is in CFLAGS_COMMON it will end up ahead of $(CC_OPT) for the
@@ -143,8 +146,8 @@
 #        Performance/size of files should be about the same, maybe smaller.
 #
 ifeq ($(FASTDEBUG), true)
-  CFLAGS_DEBUG_OPTION    = -g  $(CC_OPT/LOWER)
-  CXXFLAGS_DEBUG_OPTION  = -g0 $(CXX_OPT/LOWER)
+  CFLAGS_DEBUG_OPTION    = -g  $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
+  CXXFLAGS_DEBUG_OPTION  = -g0 $(CXX_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
 endif
 
 CFLAGS_COMMON   = -L$(OBJDIR)
--- a/jdk/make/common/Defs-windows.gmk	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/common/Defs-windows.gmk	Wed Jul 05 16:50:32 2017 +0200
@@ -111,6 +111,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 ifeq ($(CC_VERSION),msvc)
   # Visual Studio .NET 2003 or VS2003 compiler option definitions:
--- a/jdk/make/common/shared/Defs-java.gmk	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/common/shared/Defs-java.gmk	Wed Jul 05 16:50:32 2017 +0200
@@ -59,7 +59,15 @@
     ADD_CLIENT_VM_OPTION = true
   endif
 endif
-JAVA_JVM_FLAGS =
+
+# Options for hotspot to turn off printing of options with fastdebug version
+#   and creating the hotspot.log file.
+JAVA_HOTSPOT_DISABLE_PRINT_VMOPTIONS = \
+   -XX:-PrintVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-LogVMOutput
+
+# JVM options
+JAVA_JVM_FLAGS = $(JAVA_HOTSPOT_DISABLE_PRINT_VMOPTIONS)
+
 ifeq ($(ADD_CLIENT_VM_OPTION), true)
   JAVA_JVM_FLAGS += -client
 endif
--- a/jdk/make/java/fdlibm/Makefile	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/java/fdlibm/Makefile	Wed Jul 05 16:50:32 2017 +0200
@@ -45,6 +45,7 @@
 ifeq ($(PLATFORM),windows)
   # Turn all optimizations off
   OPTIMIZATION_LEVEL = NONE
+  FASTDEBUG_OPTIMIZATION_LEVEL = NONE
   OTHER_CFLAGS =
   CPPFLAGS_DBG += -DLOGGING
 endif
@@ -56,6 +57,7 @@
 ifeq ($(PLATFORM),linux)
   # Turn all optimizations off
   OPTIMIZATION_LEVEL = NONE
+  FASTDEBUG_OPTIMIZATION_LEVEL = NONE
 endif
 
 #
--- a/jdk/make/jprt.properties	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/jprt.properties	Wed Jul 05 16:50:32 2017 +0200
@@ -53,6 +53,19 @@
 
 # Standard list of jprt test targets for this workspace
 jprt.test.targets=*-*-*-jvm98
+jprt.regression.test.targets=  \
+   *-*-*-java/lang,            \
+   *-*-*-java/security,        \
+   *-*-*-java/text,            \
+   *-*-*-java/util
+
+#jprt.regression.test.targets=   \
+#   *-*-*-java/awt,       \
+#   *-*-*-java/beans,     \
+#   *-*-*-java/io,        \
+#   *-*-*-java/net,       \
+#   *-*-*-java/nio,       \
+#   *-*-*-java/rmi,       \
 
 # Directories needed to build
 jprt.bundle.exclude.src.dirs=build
--- a/jdk/make/sun/awt/Makefile	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/sun/awt/Makefile	Wed Jul 05 16:50:32 2017 +0200
@@ -339,8 +339,7 @@
 
 FONTCONFIGS_SRC = $(PLATFORM_SRC)/classes/sun/awt/windows
 _FONTCONFIGS = \
-        fontconfig.properties \
-        fontconfig.98.properties 
+        fontconfig.properties
 
 FONTCONFIGS_SRC_PREFIX =
 
--- a/jdk/make/sun/xawt/mapfile-vers	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/make/sun/xawt/mapfile-vers	Wed Jul 05 16:50:32 2017 +0200
@@ -304,12 +304,14 @@
         Java_java_awt_FileDialog_initIDs;
         Java_sun_awt_X11_XWindow_initIDs;
 
+        Java_sun_java2d_opengl_OGLContext_getOGLIdString;
         Java_sun_java2d_opengl_OGLMaskFill_maskFill;
         Java_sun_java2d_opengl_OGLRenderer_drawPoly;
         Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer;
         Java_sun_java2d_opengl_OGLSurfaceData_initTexture;
         Java_sun_java2d_opengl_OGLSurfaceData_initFBObject;
         Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer;
+        Java_sun_java2d_opengl_OGLSurfaceData_getTextureID;
         Java_sun_java2d_opengl_OGLSurfaceData_getTextureTarget;
         Java_sun_java2d_opengl_OGLTextRenderer_drawGlyphList;
         Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo;
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java	Wed Jul 05 16:50:32 2017 +0200
@@ -153,7 +153,7 @@
         node.setAttribute("imageWidth", Integer.toString(imageWidth));
         node.setAttribute("imageHeight", Integer.toString(imageHeight));
         node.setAttribute("interlaceFlag",
-                          interlaceFlag ? "true" : "false");
+                          interlaceFlag ? "TRUE" : "FALSE");
         root.appendChild(node);
 
         // Local color table
@@ -185,9 +185,9 @@
         node.setAttribute("disposalMethod",
                           disposalMethodNames[disposalMethod]);
         node.setAttribute("userInputFlag",
-                          userInputFlag ? "true" : "false");
+                          userInputFlag ? "TRUE" : "FALSE");
         node.setAttribute("transparentColorFlag",
-                          transparentColorFlag ? "true" : "false");
+                          transparentColorFlag ? "TRUE" : "FALSE");
         node.setAttribute("delayTime",
                           Integer.toString(delayTime));
         node.setAttribute("transparentColorIndex",
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Wed Jul 05 16:50:32 2017 +0200
@@ -55,6 +55,7 @@
 import org.w3c.dom.NodeList;
 import com.sun.imageio.plugins.common.LZWCompressor;
 import com.sun.imageio.plugins.common.PaletteBuilder;
+import sun.awt.image.ByteComponentRaster;
 
 public class GIFImageWriter extends ImageWriter {
     private static final boolean DEBUG = false; // XXX false for release!
@@ -905,10 +906,18 @@
         LZWCompressor compressor =
             new LZWCompressor(stream, initCodeSize, false);
 
+        /* At this moment we know that input image is indexed image.
+         * We can directly copy data iff:
+         *   - no subsampling required (periodX = 1, periodY = 0)
+         *   - we can access data directly (image is non-tiled,
+         *     i.e. image data are in single block)
+         *   - we can calculate offset in data buffer (next 3 lines)
+         */
         boolean isOptimizedCase =
             periodX == 1 && periodY == 1 &&
+            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
             sampleModel instanceof ComponentSampleModel &&
-            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
+            image.getTile(0, 0) instanceof ByteComponentRaster &&
             image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte;
 
         int numRowsWritten = 0;
@@ -921,11 +930,14 @@
             if (DEBUG) System.out.println("Writing interlaced");
 
             if (isOptimizedCase) {
-                Raster tile = image.getTile(0, 0);
+                ByteComponentRaster tile =
+                    (ByteComponentRaster)image.getTile(0, 0);
                 byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
                 ComponentSampleModel csm =
                     (ComponentSampleModel)tile.getSampleModel();
                 int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
+                // take into account the raster data offset
+                offset += tile.getDataOffset(0);
                 int lineStride = csm.getScanlineStride();
 
                 writeRowsOpt(data, offset, lineStride, compressor,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java	Wed Jul 05 16:50:32 2017 +0200
@@ -158,13 +158,10 @@
             }
         }
         String value = attr.getNodeValue();
-        // XXX Should be able to use equals() here instead of
-        // equalsIgnoreCase() but some boolean attributes are incorrectly
-        // set to "true" or "false" by the J2SE core metadata classes
-        // getAsTree() method (which are duplicated above). See bug 5082756.
-        if (value.equalsIgnoreCase("TRUE")) {
+        // Allow lower case booleans for backward compatibility, #5082756
+        if (value.equals("TRUE") || value.equals("true")) {
             return true;
-        } else if (value.equalsIgnoreCase("FALSE")) {
+        } else if (value.equals("FALSE") || value.equals("false")) {
             return false;
         } else {
             fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java	Wed Jul 05 16:50:32 2017 +0200
@@ -202,7 +202,7 @@
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("Lossless");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         compression_node.appendChild(node);
 
         // NumProgressiveScans not in stream
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Wed Jul 05 16:50:32 2017 +0200
@@ -1003,7 +1003,7 @@
                                                3,
                                                new int [] {0, 1, 2},
                                                null);
-            ColorModel cm = new ComponentColorModel(JPEG.sRGB,
+            ColorModel cm = new ComponentColorModel(JPEG.JCS.sRGB,
                                                     false,
                                                     false,
                                                     ColorModel.OPAQUE,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Wed Jul 05 16:50:32 2017 +0200
@@ -208,15 +208,24 @@
 
     public static final int [] bOffsRGB = { 2, 1, 0 };
 
-    protected static final ColorSpace sRGB =
-        ColorSpace.getInstance(ColorSpace.CS_sRGB);
-    protected static ColorSpace YCC = null;  // Can't be final
+    /* These are kept in the inner class to avoid static initialization
+     * of the CMM class until someone actually needs it.
+     * (e.g. do not init CMM on the request for jpeg mime types)
+     */
+    public static class JCS {
+        public static final ColorSpace sRGB =
+            ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        public static final ColorSpace YCC;
 
-    static {
-        try {
-            YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
-        } catch (IllegalArgumentException e) {
-            // PYCC.pf may not always be installed
+        static {
+            ColorSpace cs = null;
+            try {
+                cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
+            } catch (IllegalArgumentException e) {
+                // PYCC.pf may not always be installed
+            } finally {
+                YCC = cs;
+            }
         }
     }
 
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 16:50:32 2017 +0200
@@ -228,31 +228,31 @@
             (BufferedImage.TYPE_BYTE_GRAY);
         defaultTypes[JPEG.JCS_RGB] =
             ImageTypeSpecifier.createInterleaved
-            (JPEG.sRGB,
+            (JPEG.JCS.sRGB,
              JPEG.bOffsRGB,
              DataBuffer.TYPE_BYTE,
              false,
              false);
         defaultTypes[JPEG.JCS_RGBA] =
             ImageTypeSpecifier.createPacked
-            (JPEG.sRGB,
+            (JPEG.JCS.sRGB,
              0xff000000,
              0x00ff0000,
              0x0000ff00,
              0x000000ff,
              DataBuffer.TYPE_INT,
              false);
-        if (JPEG.YCC != null) {
+        if (JPEG.JCS.YCC != null) {
             defaultTypes[JPEG.JCS_YCC] =
                 ImageTypeSpecifier.createInterleaved
-                (JPEG.YCC,
+                (JPEG.JCS.YCC,
                  JPEG.bandOffsets[2],
                  DataBuffer.TYPE_BYTE,
                  false,
                  false);
             defaultTypes[JPEG.JCS_YCCA] =
                 ImageTypeSpecifier.createInterleaved
-                (JPEG.YCC,
+                (JPEG.JCS.YCC,
                  JPEG.bandOffsets[3],
                  DataBuffer.TYPE_BYTE,
                  true,
@@ -774,7 +774,7 @@
         case JPEG.JCS_RGB:
             list.add(raw);
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.YCC != null) {
+            if (JPEG.JCS.YCC != null) {
                 list.add(getImageType(JPEG.JCS_YCC));
             }
             break;
@@ -811,7 +811,7 @@
             }
 
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.YCC != null) { // Might be null if PYCC.pf not installed
+            if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed
                 list.add(getImageType(JPEG.JCS_YCC));
             }
             break;
@@ -893,7 +893,7 @@
                        (!cs.isCS_sRGB()) &&
                        (cm.getNumComponents() == numComponents)) {
                 // Target isn't sRGB, so convert from sRGB to the target
-                convert = new ColorConvertOp(JPEG.sRGB, cs, null);
+                convert = new ColorConvertOp(JPEG.JCS.sRGB, cs, null);
             } else if (csType != ColorSpace.TYPE_RGB) {
                 throw new IIOException("Incompatible color conversion");
             }
@@ -906,18 +906,18 @@
             }
             break;
         case JPEG.JCS_YCC:
-            if (JPEG.YCC == null) { // We can't do YCC at all
+            if (JPEG.JCS.YCC == null) { // We can't do YCC at all
                 throw new IIOException("Incompatible color conversion");
             }
-            if ((cs != JPEG.YCC) &&
+            if ((cs != JPEG.JCS.YCC) &&
                 (cm.getNumComponents() == numComponents)) {
-                convert = new ColorConvertOp(JPEG.YCC, cs, null);
+                convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null);
             }
             break;
         case JPEG.JCS_YCCA:
             // No conversions available; image must be YCCA
-            if ((JPEG.YCC == null) || // We can't do YCC at all
-                (cs != JPEG.YCC) ||
+            if ((JPEG.JCS.YCC == null) || // We can't do YCC at all
+                (cs != JPEG.JCS.YCC) ||
                 (cm.getNumComponents() != numComponents)) {
                 throw new IIOException("Incompatible color conversion");
             }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Wed Jul 05 16:50:32 2017 +0200
@@ -39,8 +39,6 @@
     private static String [] writerSpiNames =
         {"com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi"};
 
-    private boolean registered = false;
-
     public JPEGImageReaderSpi() {
         super(JPEG.vendor,
               JPEG.version,
@@ -61,26 +59,6 @@
               );
     }
 
-    public void onRegistration(ServiceRegistry registry,
-                               Class<?> category) {
-        if (registered) {
-            return;
-        }
-        try {
-            java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("jpeg"));
-            // Stuff it all into one lib for first pass
-            //java.security.AccessController.doPrivileged(
-            //new sun.security.action.LoadLibraryAction("imageioIJG"));
-        } catch (Throwable e) { // Fail on any Throwable
-            // if it can't be loaded, deregister and return
-            registry.deregisterServiceProvider(this);
-            return;
-        }
-
-        registered = true;
-    }
-
     public String getDescription(Locale locale) {
         return "Standard JPEG Image Reader";
     }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 16:50:32 2017 +0200
@@ -812,13 +812,13 @@
                             }
                             break;
                         case ColorSpace.TYPE_3CLR:
-                            if (cs == JPEG.YCC) {
+                            if (cs == JPEG.JCS.YCC) {
                                 if (!alpha) {
                                     if (jfif != null) {
                                         convertTosRGB = true;
                                         convertOp =
                                         new ColorConvertOp(cs,
-                                                           JPEG.sRGB,
+                                                           JPEG.JCS.sRGB,
                                                            null);
                                         outCsType = JPEG.JCS_YCbCr;
                                     } else if (adobe != null) {
@@ -1494,7 +1494,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1533,7 +1533,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1579,7 +1579,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Wed Jul 05 16:50:32 2017 +0200
@@ -42,8 +42,6 @@
     private static String [] readerSpiNames =
         {"com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi"};
 
-    private boolean registered = false;
-
     public JPEGImageWriterSpi() {
         super(JPEG.vendor,
               JPEG.version,
@@ -68,23 +66,6 @@
         return "Standard JPEG Image Writer";
     }
 
-    public void onRegistration(ServiceRegistry registry,
-                               Class<?> category) {
-        if (registered) {
-            return;
-        }
-        try {
-            java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("jpeg"));
-        } catch (Throwable e) { // Fail on any Throwable
-            // if it can't be loaded, deregister and return
-            registry.deregisterServiceProvider(this);
-            return;
-        }
-
-        registered = true;
-    }
-
     public boolean isFormatLossless() {
         return false;
     }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Wed Jul 05 16:50:32 2017 +0200
@@ -490,7 +490,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     wantJFIF = false;
                     componentIDs[0] = (byte) 'Y';
                     componentIDs[1] = (byte) 'C';
@@ -955,7 +955,7 @@
 
         // Lossless - false
         IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
-        lossless.setAttribute("value", "false");
+        lossless.setAttribute("value", "FALSE");
         compression.appendChild(lossless);
 
         // NumProgressiveScans - count sos segments
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Wed Jul 05 16:50:32 2017 +0200
@@ -37,6 +37,7 @@
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
+import java.io.EOFException;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.SequenceInputStream;
@@ -59,7 +60,7 @@
 import java.io.ByteArrayOutputStream;
 import sun.awt.image.ByteInterleavedRaster;
 
-class PNGImageDataEnumeration implements Enumeration {
+class PNGImageDataEnumeration implements Enumeration<InputStream> {
 
     boolean firstTime = true;
     ImageInputStream stream;
@@ -72,7 +73,7 @@
         int type = stream.readInt(); // skip chunk type
     }
 
-    public Object nextElement() {
+    public InputStream nextElement() {
         try {
             firstTime = false;
             ImageInputStream iis = new SubImageInputStream(stream, length);
@@ -207,25 +208,17 @@
         resetStreamSettings();
     }
 
-    private String readNullTerminatedString(String charset) throws IOException {
+    private String readNullTerminatedString(String charset, int maxLen) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         int b;
-        while ((b = stream.read()) != 0) {
+        int count = 0;
+        while ((maxLen > count++) && ((b = stream.read()) != 0)) {
+            if (b == -1) throw new EOFException();
             baos.write(b);
         }
         return new String(baos.toByteArray(), charset);
     }
 
-    private String readNullTerminatedString() throws IOException {
-        StringBuilder b = new StringBuilder();
-        int c;
-
-        while ((c = stream.read()) != 0) {
-            b.append((char)c);
-        }
-        return b.toString();
-    }
-
     private void readHeader() throws IIOException {
         if (gotHeader) {
             return;
@@ -434,7 +427,7 @@
     }
 
     private void parse_iCCP_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.iCCP_profileName = keyword;
 
         metadata.iCCP_compressionMethod = stream.readUnsignedByte();
@@ -450,7 +443,7 @@
     private void parse_iTXt_chunk(int chunkLength) throws IOException {
         long chunkStart = stream.getStreamPosition();
 
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.iTXt_keyword.add(keyword);
 
         int compressionFlag = stream.readUnsignedByte();
@@ -459,15 +452,17 @@
         int compressionMethod = stream.readUnsignedByte();
         metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
 
-        String languageTag = readNullTerminatedString("UTF8");
+        String languageTag = readNullTerminatedString("UTF8", 80);
         metadata.iTXt_languageTag.add(languageTag);
 
+        long pos = stream.getStreamPosition();
+        int maxLen = (int)(chunkStart + chunkLength - pos);
         String translatedKeyword =
-            readNullTerminatedString("UTF8");
+            readNullTerminatedString("UTF8", maxLen);
         metadata.iTXt_translatedKeyword.add(translatedKeyword);
 
         String text;
-        long pos = stream.getStreamPosition();
+        pos = stream.getStreamPosition();
         byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
         stream.readFully(b);
 
@@ -511,7 +506,7 @@
 
     private void parse_sPLT_chunk(int chunkLength)
         throws IOException, IIOException {
-        metadata.sPLT_paletteName = readNullTerminatedString();
+        metadata.sPLT_paletteName = readNullTerminatedString("ISO-8859-1", 80);
         chunkLength -= metadata.sPLT_paletteName.length() + 1;
 
         int sampleDepth = stream.readUnsignedByte();
@@ -554,12 +549,12 @@
     }
 
     private void parse_tEXt_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.tEXt_keyword.add(keyword);
 
         byte[] b = new byte[chunkLength - keyword.length() - 1];
         stream.readFully(b);
-        metadata.tEXt_text.add(new String(b));
+        metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
     }
 
     private void parse_tIME_chunk() throws IOException {
@@ -640,7 +635,7 @@
     }
 
     private void parse_zTXt_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.zTXt_keyword.add(keyword);
 
         int method = stream.readUnsignedByte();
@@ -648,7 +643,7 @@
 
         byte[] b = new byte[chunkLength - keyword.length() - 2];
         stream.readFully(b);
-        metadata.zTXt_text.add(new String(inflate(b)));
+        metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
     }
 
     private void readMetadata() throws IIOException {
@@ -1263,7 +1258,7 @@
         try {
             stream.seek(imageStartPosition);
 
-            Enumeration e = new PNGImageDataEnumeration(stream);
+            Enumeration<InputStream> e = new PNGImageDataEnumeration(stream);
             InputStream is = new SequenceInputStream(e);
 
            /* InflaterInputStream uses an Inflater instance which consumes
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java	Wed Jul 05 16:50:32 2017 +0200
@@ -674,13 +674,8 @@
     private byte[] deflate(byte[] b) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DeflaterOutputStream dos = new DeflaterOutputStream(baos);
-
-        int len = b.length;
-        for (int i = 0; i < len; i++) {
-            dos.write((int)(0xff & b[i]));
-        }
+        dos.write(b);
         dos.close();
-
         return baos.toByteArray();
     }
 
@@ -736,7 +731,7 @@
             cs.writeByte(compressionMethod);
 
             String text = (String)textIter.next();
-            cs.write(deflate(text.getBytes()));
+            cs.write(deflate(text.getBytes("ISO-8859-1")));
             cs.finish();
         }
     }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java	Wed Jul 05 16:50:32 2017 +0200
@@ -211,8 +211,8 @@
     public int sRGB_renderingIntent;
 
     // tEXt chunk
-    public ArrayList tEXt_keyword = new ArrayList(); // 1-79 char Strings
-    public ArrayList tEXt_text = new ArrayList(); // Strings
+    public ArrayList<String> tEXt_keyword = new ArrayList<String>(); // 1-79 characters
+    public ArrayList<String> tEXt_text = new ArrayList<String>();
 
     // tIME chunk
     public boolean tIME_present;
@@ -235,13 +235,13 @@
     public int tRNS_blue;
 
     // zTXt chunk
-    public ArrayList zTXt_keyword = new ArrayList(); // Strings
-    public ArrayList zTXt_compressionMethod = new ArrayList(); // Integers
-    public ArrayList zTXt_text = new ArrayList(); // Strings
+    public ArrayList<String> zTXt_keyword = new ArrayList<String>();
+    public ArrayList<Integer> zTXt_compressionMethod = new ArrayList<Integer>();
+    public ArrayList<String> zTXt_text = new ArrayList<String>();
 
     // Unknown chunks
-    public ArrayList unknownChunkType = new ArrayList(); // Strings
-    public ArrayList unknownChunkData = new ArrayList(); // byte arrays
+    public ArrayList<String> unknownChunkType = new ArrayList<String>();
+    public ArrayList<byte[]> unknownChunkData = new ArrayList<byte[]>();
 
     public PNGMetadata() {
         super(true,
@@ -426,21 +426,14 @@
         return false;
     }
 
-    private ArrayList cloneBytesArrayList(ArrayList in) {
+    private ArrayList<byte[]> cloneBytesArrayList(ArrayList<byte[]> in) {
         if (in == null) {
             return null;
         } else {
-            ArrayList list = new ArrayList(in.size());
-            Iterator iter = in.iterator();
-            while (iter.hasNext()) {
-                Object o = iter.next();
-                if (o == null) {
-                    list.add(null);
-                } else {
-                    list.add(((byte[])o).clone());
-                }
+            ArrayList<byte[]> list = new ArrayList<byte[]>(in.size());
+            for (byte[] b: in) {
+                list.add((b == null) ? null : (byte[])b.clone());
             }
-
             return list;
         }
     }
@@ -600,7 +593,7 @@
                 IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
                 iTXt_node.setAttribute("keyword", iTXt_keyword.get(i));
                 iTXt_node.setAttribute("compressionFlag",
-                        iTXt_compressionFlag.get(i) ? "1" : "0");
+                        iTXt_compressionFlag.get(i) ? "TRUE" : "FALSE");
                 iTXt_node.setAttribute("compressionMethod",
                         iTXt_compressionMethod.get(i).toString());
                 iTXt_node.setAttribute("languageTag",
@@ -832,7 +825,7 @@
         }
 
         node = new IIOMetadataNode("BlackIsZero");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         chroma_node.appendChild(node);
 
         if (PLTE_present) {
@@ -894,7 +887,7 @@
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("Lossless");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("NumProgressiveScans");
@@ -1040,7 +1033,7 @@
             node.setAttribute("language",
                               iTXt_languageTag.get(i));
             if (iTXt_compressionFlag.get(i)) {
-                node.setAttribute("compression", "deflate");
+                node.setAttribute("compression", "zip");
             } else {
                 node.setAttribute("compression", "none");
             }
@@ -1052,7 +1045,7 @@
             node = new IIOMetadataNode("TextEntry");
             node.setAttribute("keyword", (String)zTXt_keyword.get(i));
             node.setAttribute("value", (String)zTXt_text.get(i));
-            node.setAttribute("compression", "deflate");
+            node.setAttribute("compression", "zip");
 
             text_node.appendChild(node);
         }
@@ -1162,12 +1155,13 @@
             }
         }
         String value = attr.getNodeValue();
-        if (value.equals("true")) {
+        // Allow lower case booleans for backward compatibility, #5082756
+        if (value.equals("TRUE") || value.equals("true")) {
             return true;
-        } else if (value.equals("false")) {
+        } else if (value.equals("FALSE") || value.equals("false")) {
             return false;
         } else {
-            fatal(node, "Attribute " + name + " must be 'true' or 'false'!");
+            fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
             return false;
         }
     }
@@ -1421,26 +1415,30 @@
                     }
 
                     String keyword = getAttribute(iTXt_node, "keyword");
-                    iTXt_keyword.add(keyword);
+                    if (isValidKeyword(keyword)) {
+                        iTXt_keyword.add(keyword);
 
-                    boolean compressionFlag =
-                        getBooleanAttribute(iTXt_node, "compressionFlag");
-                    iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
+                        boolean compressionFlag =
+                            getBooleanAttribute(iTXt_node, "compressionFlag");
+                        iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
 
-                    String compressionMethod =
-                        getAttribute(iTXt_node, "compressionMethod");
-                    iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
+                        String compressionMethod =
+                            getAttribute(iTXt_node, "compressionMethod");
+                        iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
 
-                    String languageTag =
-                        getAttribute(iTXt_node, "languageTag");
-                    iTXt_languageTag.add(languageTag);
+                        String languageTag =
+                            getAttribute(iTXt_node, "languageTag");
+                        iTXt_languageTag.add(languageTag);
 
-                    String translatedKeyword =
-                        getAttribute(iTXt_node, "translatedKeyword");
-                    iTXt_translatedKeyword.add(translatedKeyword);
+                        String translatedKeyword =
+                            getAttribute(iTXt_node, "translatedKeyword");
+                        iTXt_translatedKeyword.add(translatedKeyword);
 
-                    String text = getAttribute(iTXt_node, "text");
-                    iTXt_text.add(text);
+                        String text = getAttribute(iTXt_node, "text");
+                        iTXt_text.add(text);
+
+                    }
+                    // silently skip invalid text entry
 
                     iTXt_node = iTXt_node.getNextSibling();
                 }
@@ -1692,11 +1690,45 @@
         }
     }
 
-    private boolean isISOLatin(String s) {
+    /*
+     * Accrding to PNG spec, keywords are restricted to 1 to 79 bytes
+     * in length. Keywords shall contain only printable Latin-1 characters
+     * and spaces; To reduce the chances for human misreading of a keyword,
+     * leading spaces, trailing spaces, and consecutive spaces are not
+     * permitted in keywords.
+     *
+     * See: http://www.w3.org/TR/PNG/#11keywords
+     */
+    private boolean isValidKeyword(String s) {
+        int len = s.length();
+        if (len < 1 || len >= 80) {
+            return false;
+        }
+        if (s.startsWith(" ") || s.endsWith(" ") || s.contains("  ")) {
+            return false;
+        }
+        return isISOLatin(s, false);
+    }
+
+    /*
+     * According to PNG spec, keyword shall contain only printable
+     * Latin-1 [ISO-8859-1] characters and spaces; that is, only
+     * character codes 32-126 and 161-255 decimal are allowed.
+     * For Latin-1 value fields the 0x10 (linefeed) control
+     * character is aloowed too.
+     *
+     * See: http://www.w3.org/TR/PNG/#11keywords
+     */
+    private boolean isISOLatin(String s, boolean isLineFeedAllowed) {
         int len = s.length();
         for (int i = 0; i < len; i++) {
-            if (s.charAt(i) > 255) {
-                return false;
+            char c = s.charAt(i);
+            if (c < 32 || c > 255 || (c > 126 && c < 161)) {
+                // not printable. Check whether this is an allowed
+                // control char
+                if (!isLineFeedAllowed || c != 0x10) {
+                    return false;
+                }
             }
         }
         return true;
@@ -1929,19 +1961,22 @@
                 while (child != null) {
                     String childName = child.getNodeName();
                     if (childName.equals("TextEntry")) {
-                        String keyword = getAttribute(child, "keyword");
+                        String keyword =
+                            getAttribute(child, "keyword", "", false);
                         String value = getAttribute(child, "value");
-                        String encoding = getAttribute(child, "encoding");
-                        String language = getAttribute(child, "language");
+                        String language =
+                            getAttribute(child, "language", "", false);
                         String compression =
-                            getAttribute(child, "compression");
+                            getAttribute(child, "compression", "none", false);
 
-                        if (isISOLatin(value)) {
+                        if (!isValidKeyword(keyword)) {
+                            // Just ignore this node, PNG requires keywords
+                        } else if (isISOLatin(value, true)) {
                             if (compression.equals("zip")) {
                                 // Use a zTXt node
                                 zTXt_keyword.add(keyword);
                                 zTXt_text.add(value);
-                                zTXt_compressionMethod.add(new Integer(0));
+                                zTXt_compressionMethod.add(Integer.valueOf(0));
                             } else {
                                 // Use a tEXt node
                                 tEXt_keyword.add(keyword);
@@ -1998,14 +2033,14 @@
         sBIT_present = false;
         sPLT_present = false;
         sRGB_present = false;
-        tEXt_keyword = new ArrayList();
-        tEXt_text = new ArrayList();
+        tEXt_keyword = new ArrayList<String>();
+        tEXt_text = new ArrayList<String>();
         tIME_present = false;
         tRNS_present = false;
-        zTXt_keyword = new ArrayList();
-        zTXt_compressionMethod = new ArrayList();
-        zTXt_text = new ArrayList();
-        unknownChunkType = new ArrayList();
-        unknownChunkData = new ArrayList();
+        zTXt_keyword = new ArrayList<String>();
+        zTXt_compressionMethod = new ArrayList<Integer>();
+        zTXt_text = new ArrayList<String>();
+        unknownChunkType = new ArrayList<String>();
+        unknownChunkData = new ArrayList<byte[]>();
     }
 }
--- a/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Wed Jul 05 16:50:32 2017 +0200
@@ -94,6 +94,10 @@
                                  tgn != null;
                                  tg = tgn, tgn = tg.getParent());
                             streamCloser = new Thread(tg, streamCloserRunnable);
+                            /* Set context class loader to null in order to avoid
+                             * keeping a strong reference to an application classloader.
+                             */
+                            streamCloser.setContextClassLoader(null);
                             Runtime.getRuntime().addShutdownHook(streamCloser);
                             return null;
                         }
--- a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Wed Jul 05 16:50:32 2017 +0200
@@ -356,6 +356,9 @@
      * @since 1.5
      */
     public void preferLocaleFonts() {
+        if (!(this instanceof SunGraphicsEnvironment)) {
+            return;
+        }
         sun.font.FontManager.preferLocaleFonts();
     }
 
@@ -376,6 +379,9 @@
      * @since 1.5
      */
     public void preferProportionalFonts() {
+        if (!(this instanceof SunGraphicsEnvironment)) {
+            return;
+        }
         sun.font.FontManager.preferProportionalFonts();
     }
 
--- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 05 16:50:32 2017 +0200
@@ -737,7 +737,7 @@
     ICC_Profile(ProfileDeferralInfo pdi) {
         this.deferralInfo = pdi;
         this.profileActivator = new ProfileActivator() {
-            public void activate() {
+            public void activate() throws ProfileDataException {
                 activateDeferredProfile();
             }
         };
@@ -830,20 +830,16 @@
         case ColorSpace.CS_sRGB:
             synchronized(ICC_Profile.class) {
                 if (sRGBprofile == null) {
-                    try {
-                        /*
-                         * Deferral is only used for standard profiles.
-                         * Enabling the appropriate access privileges is handled
-                         * at a lower level.
-                         */
-                        sRGBprofile = getDeferredInstance(
-                            new ProfileDeferralInfo("sRGB.pf",
-                                                    ColorSpace.TYPE_RGB,
-                                                    3, CLASS_DISPLAY));
-                    } catch (IOException e) {
-                        throw new IllegalArgumentException(
-                              "Can't load standard profile: sRGB.pf");
-                    }
+                    /*
+                     * Deferral is only used for standard profiles.
+                     * Enabling the appropriate access privileges is handled
+                     * at a lower level.
+                     */
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("sRGB.pf",
+                                                ColorSpace.TYPE_RGB, 3,
+                                                CLASS_DISPLAY);
+                    sRGBprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = sRGBprofile;
             }
@@ -853,7 +849,11 @@
         case ColorSpace.CS_CIEXYZ:
             synchronized(ICC_Profile.class) {
                 if (XYZprofile == null) {
-                    XYZprofile = getStandardProfile("CIEXYZ.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("CIEXYZ.pf",
+                                                ColorSpace.TYPE_XYZ, 3,
+                                                CLASS_DISPLAY);
+                    XYZprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = XYZprofile;
             }
@@ -863,7 +863,11 @@
         case ColorSpace.CS_PYCC:
             synchronized(ICC_Profile.class) {
                 if (PYCCprofile == null) {
-                    PYCCprofile = getStandardProfile("PYCC.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("PYCC.pf",
+                                                ColorSpace.TYPE_3CLR, 3,
+                                                CLASS_DISPLAY);
+                    PYCCprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = PYCCprofile;
             }
@@ -873,7 +877,11 @@
         case ColorSpace.CS_GRAY:
             synchronized(ICC_Profile.class) {
                 if (GRAYprofile == null) {
-                    GRAYprofile = getStandardProfile("GRAY.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("GRAY.pf",
+                                                ColorSpace.TYPE_GRAY, 1,
+                                                CLASS_DISPLAY);
+                    GRAYprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = GRAYprofile;
             }
@@ -883,7 +891,11 @@
         case ColorSpace.CS_LINEAR_RGB:
             synchronized(ICC_Profile.class) {
                 if (LINEAR_RGBprofile == null) {
-                    LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("LINEAR_RGB.pf",
+                                                ColorSpace.TYPE_RGB, 3,
+                                                CLASS_DISPLAY);
+                    LINEAR_RGBprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = LINEAR_RGBprofile;
             }
@@ -1047,9 +1059,7 @@
      * code will take care of access privileges.
      * @see activateDeferredProfile()
      */
-    static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi)
-        throws IOException {
-
+    static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
         if (!ProfileDeferralMgr.deferring) {
             return getStandardProfile(pdi.filename);
         }
@@ -1063,33 +1073,37 @@
     }
 
 
-    void activateDeferredProfile() {
-    byte profileData[];
-    FileInputStream fis;
-    String fileName = deferralInfo.filename;
+    void activateDeferredProfile() throws ProfileDataException {
+        byte profileData[];
+        FileInputStream fis;
+        String fileName = deferralInfo.filename;
 
         profileActivator = null;
         deferralInfo = null;
         if ((fis = openProfile(fileName)) == null) {
-            throw new IllegalArgumentException("Cannot open file " + fileName);
+            throw new ProfileDataException("Cannot open file " + fileName);
         }
         try {
             profileData = getProfileDataFromStream(fis);
             fis.close();    /* close the file */
         }
         catch (IOException e) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
-                fileName);
+            ProfileDataException pde = new
+                ProfileDataException("Invalid ICC Profile Data" + fileName);
+            pde.initCause(e);
+            throw pde;
         }
         if (profileData == null) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
+            throw new ProfileDataException("Invalid ICC Profile Data" +
                 fileName);
         }
         try {
             ID = CMSManager.getModule().loadProfile(profileData);
         } catch (CMMException c) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
-                fileName);
+            ProfileDataException pde = new
+                ProfileDataException("Invalid ICC Profile Data" + fileName);
+            pde.initCause(c);
+            throw pde;
         }
     }
 
--- a/jdk/src/share/classes/java/util/logging/LogManager.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 16:50:32 2017 +0200
@@ -215,6 +215,14 @@
     // This private class is used as a shutdown hook.
     // It does a "reset" to close all open handlers.
     private class Cleaner extends Thread {
+
+        private Cleaner() {
+            /* Set context class loader to null in order to avoid
+             * keeping a strong reference to an application classloader.
+             */
+            this.setContextClassLoader(null);
+        }
+
         public void run() {
             // This is to ensure the LogManager.<clinit> is completed
             // before synchronized block. Otherwise deadlocks are possible.
--- a/jdk/src/share/classes/javax/imageio/ImageTypeSpecifier.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/javax/imageio/ImageTypeSpecifier.java	Wed Jul 05 16:50:32 2017 +0200
@@ -67,126 +67,13 @@
      * <code>BufferedImage</code> types.
      */
     private static ImageTypeSpecifier[] BISpecifier;
-
+    private static ColorSpace sRGB;
     // Initialize the standard specifiers
     static {
-        ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 
         BISpecifier =
             new ImageTypeSpecifier[BufferedImage.TYPE_BYTE_INDEXED + 1];
-
-        BISpecifier[BufferedImage.TYPE_CUSTOM] = null;
-
-        BISpecifier[BufferedImage.TYPE_INT_RGB] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0x0,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_INT_ARGB] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0xff000000,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_INT_ARGB_PRE] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0xff000000,
-                         DataBuffer.TYPE_INT,
-                         true);
-
-        BISpecifier[BufferedImage.TYPE_INT_BGR] =
-            createPacked(sRGB,
-                         0x000000ff,
-                         0x0000ff00,
-                         0x00ff0000,
-                         0x0,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        int[] bOffsRGB = { 2, 1, 0 };
-        BISpecifier[BufferedImage.TYPE_3BYTE_BGR] =
-            createInterleaved(sRGB,
-                              bOffsRGB,
-                              DataBuffer.TYPE_BYTE,
-                              false,
-                              false);
-
-        int[] bOffsABGR = { 3, 2, 1, 0 };
-        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR] =
-            createInterleaved(sRGB,
-                              bOffsABGR,
-                              DataBuffer.TYPE_BYTE,
-                              true,
-                              false);
-
-        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR_PRE] =
-            createInterleaved(sRGB,
-                              bOffsABGR,
-                              DataBuffer.TYPE_BYTE,
-                              true,
-                              true);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_565_RGB] =
-            createPacked(sRGB,
-                         0xF800,
-                         0x07E0,
-                         0x001F,
-                         0x0,
-                         DataBuffer.TYPE_USHORT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_555_RGB] =
-            createPacked(sRGB,
-                         0x7C00,
-                         0x03E0,
-                         0x001F,
-                         0x0,
-                         DataBuffer.TYPE_USHORT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_GRAY] =
-            createGrayscale(8,
-                            DataBuffer.TYPE_BYTE,
-                            false);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_GRAY] =
-            createGrayscale(16,
-                            DataBuffer.TYPE_USHORT,
-                            false);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_BINARY] =
-            createGrayscale(1,
-                            DataBuffer.TYPE_BYTE,
-                            false);
-
-        BufferedImage bi =
-            new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
-        IndexColorModel icm = (IndexColorModel)bi.getColorModel();
-        int mapSize = icm.getMapSize();
-        byte[] redLUT = new byte[mapSize];
-        byte[] greenLUT = new byte[mapSize];
-        byte[] blueLUT = new byte[mapSize];
-        byte[] alphaLUT = new byte[mapSize];
-
-        icm.getReds(redLUT);
-        icm.getGreens(greenLUT);
-        icm.getBlues(blueLUT);
-        icm.getAlphas(alphaLUT);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_INDEXED] =
-            createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
-                          8,
-                          DataBuffer.TYPE_BYTE);
     }
 
     /**
@@ -1011,7 +898,7 @@
         ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
         if (bufferedImageType >= BufferedImage.TYPE_INT_RGB &&
             bufferedImageType <= BufferedImage.TYPE_BYTE_INDEXED) {
-            return BISpecifier[bufferedImageType];
+            return getSpecifier(bufferedImageType);
         } else if (bufferedImageType == BufferedImage.TYPE_CUSTOM) {
             throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
         } else {
@@ -1041,7 +928,7 @@
         if (image instanceof BufferedImage) {
             int bufferedImageType = ((BufferedImage)image).getType();
             if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
-                return BISpecifier[bufferedImageType];
+                return getSpecifier(bufferedImageType);
             }
         }
 
@@ -1225,4 +1112,130 @@
     public int hashCode() {
         return (9 * colorModel.hashCode()) + (14 * sampleModel.hashCode());
     }
+
+    private static ImageTypeSpecifier getSpecifier(int type) {
+        if (BISpecifier[type] == null) {
+            BISpecifier[type] = createSpecifier(type);
+        }
+        return BISpecifier[type];
+    }
+
+    private static ImageTypeSpecifier createSpecifier(int type) {
+        switch(type) {
+          case BufferedImage.TYPE_INT_RGB:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0x0,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_INT_ARGB:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0xff000000,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_INT_ARGB_PRE:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0xff000000,
+                                  DataBuffer.TYPE_INT,
+                                  true);
+
+          case BufferedImage.TYPE_INT_BGR:
+              return createPacked(sRGB,
+                                  0x000000ff,
+                                  0x0000ff00,
+                                  0x00ff0000,
+                                  0x0,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_3BYTE_BGR:
+              return createInterleaved(sRGB,
+                                       new int[] { 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       false,
+                                       false);
+
+          case BufferedImage.TYPE_4BYTE_ABGR:
+              return createInterleaved(sRGB,
+                                       new int[] { 3, 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       true,
+                                       false);
+
+          case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+              return createInterleaved(sRGB,
+                                       new int[] { 3, 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       true,
+                                       true);
+
+          case BufferedImage.TYPE_USHORT_565_RGB:
+              return createPacked(sRGB,
+                                  0xF800,
+                                  0x07E0,
+                                  0x001F,
+                                  0x0,
+                                  DataBuffer.TYPE_USHORT,
+                                  false);
+
+          case BufferedImage.TYPE_USHORT_555_RGB:
+              return createPacked(sRGB,
+                                  0x7C00,
+                                  0x03E0,
+                                  0x001F,
+                                  0x0,
+                                  DataBuffer.TYPE_USHORT,
+                                  false);
+
+          case BufferedImage.TYPE_BYTE_GRAY:
+            return createGrayscale(8,
+                                   DataBuffer.TYPE_BYTE,
+                                   false);
+
+          case BufferedImage.TYPE_USHORT_GRAY:
+            return createGrayscale(16,
+                                   DataBuffer.TYPE_USHORT,
+                                   false);
+
+          case BufferedImage.TYPE_BYTE_BINARY:
+              return createGrayscale(1,
+                                     DataBuffer.TYPE_BYTE,
+                                     false);
+
+          case BufferedImage.TYPE_BYTE_INDEXED:
+          {
+
+              BufferedImage bi =
+                  new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
+              IndexColorModel icm = (IndexColorModel)bi.getColorModel();
+              int mapSize = icm.getMapSize();
+              byte[] redLUT = new byte[mapSize];
+              byte[] greenLUT = new byte[mapSize];
+              byte[] blueLUT = new byte[mapSize];
+              byte[] alphaLUT = new byte[mapSize];
+
+              icm.getReds(redLUT);
+              icm.getGreens(greenLUT);
+              icm.getBlues(blueLUT);
+              icm.getAlphas(alphaLUT);
+
+              return createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
+                                   8,
+                                   DataBuffer.TYPE_BYTE);
+          }
+          default:
+              throw new IllegalArgumentException("Invalid BufferedImage type!");
+        }
+    }
+
 }
--- a/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java	Wed Jul 05 16:50:32 2017 +0200
@@ -242,8 +242,12 @@
 
     /**
      * A constant returned by <code>getAttributeDataType</code>
-     * indicating that the value of an attribute is one of 'true' or
-     * 'false'.
+     * indicating that the value of an attribute is one of the boolean
+     * values 'true' or 'false'.
+     * Attribute values of type DATATYPE_BOOLEAN should be marked as
+     * enumerations, and the permitted values should be the string
+     * literal values "TRUE" or "FALSE", although a plugin may also
+     * recognise lower or mixed case equivalents.
      */
     int DATATYPE_BOOLEAN = 1;
 
--- a/jdk/src/share/classes/sun/awt/FontConfiguration.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java	Wed Jul 05 16:50:32 2017 +0200
@@ -98,7 +98,7 @@
         if (!inited) {
             this.preferLocaleFonts = false;
             this.preferPropFonts = false;
-            fontConfig = this;      /* static initialization */
+            setFontConfiguration();
             readFontConfigFile(fontConfigFile);
             initFontConfig();
             inited = true;
@@ -1244,6 +1244,10 @@
         return fontConfig;
     }
 
+    protected void setFontConfiguration() {
+        fontConfig = this;      /* static initialization */
+    }
+
     //////////////////////////////////////////////////////////////////////
     // FontConfig data tables and the index constants in binary file    //
     //////////////////////////////////////////////////////////////////////
--- a/jdk/src/share/classes/sun/font/FileFontStrike.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/font/FileFontStrike.java	Wed Jul 05 16:50:32 2017 +0200
@@ -26,6 +26,7 @@
 package sun.font;
 
 import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
 import java.awt.Font;
 import java.awt.GraphicsEnvironment;
 import java.awt.Rectangle;
@@ -842,8 +843,36 @@
         return fileFont.getGlyphOutlineBounds(pScalerContext, glyphCode);
     }
 
+    private
+        WeakReference<ConcurrentHashMap<Integer,GeneralPath>> outlineMapRef;
+
     GeneralPath getGlyphOutline(int glyphCode, float x, float y) {
-        return fileFont.getGlyphOutline(pScalerContext, glyphCode, x, y);
+
+        GeneralPath gp = null;
+        ConcurrentHashMap<Integer, GeneralPath> outlineMap = null;
+
+        if (outlineMapRef != null) {
+            outlineMap = outlineMapRef.get();
+            if (outlineMap != null) {
+                gp = (GeneralPath)outlineMap.get(glyphCode);
+            }
+        }
+
+        if (gp == null) {
+            gp = fileFont.getGlyphOutline(pScalerContext, glyphCode, 0, 0);
+            if (outlineMap == null) {
+                outlineMap = new ConcurrentHashMap<Integer, GeneralPath>();
+                outlineMapRef =
+                   new WeakReference
+                       <ConcurrentHashMap<Integer,GeneralPath>>(outlineMap);
+            }
+            outlineMap.put(glyphCode, gp);
+        }
+        gp = (GeneralPath)gp.clone(); // mutable!
+        if (x != 0f || y != 0f) {
+            gp.transform(AffineTransform.getTranslateInstance(x, y));
+        }
+        return gp;
     }
 
     GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) {
--- a/jdk/src/share/classes/sun/font/FontManager.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/font/FontManager.java	Wed Jul 05 16:50:32 2017 +0200
@@ -1601,18 +1601,27 @@
     /* Path may be absolute or a base file name relative to one of
      * the platform font directories
      */
-    private static String getPathName(String s) {
+    private static String getPathName(final String s) {
         File f = new File(s);
         if (f.isAbsolute()) {
             return s;
         } else if (pathDirs.length==1) {
             return pathDirs[0] + File.separator + s;
         } else {
-            for (int p=0; p<pathDirs.length; p++) {
-                f = new File(pathDirs[p] + File.separator + s);
-                if (f.exists()) {
-                    return f.getAbsolutePath();
-                }
+            String path = java.security.AccessController.doPrivileged(
+                 new java.security.PrivilegedAction<String>() {
+                     public String run() {
+                         for (int p=0; p<pathDirs.length; p++) {
+                             File f = new File(pathDirs[p] +File.separator+ s);
+                             if (f.exists()) {
+                                 return f.getAbsolutePath();
+                             }
+                         }
+                         return null;
+                     }
+                });
+            if (path != null) {
+                return path;
             }
         }
         return s; // shouldn't happen, but harmless
--- a/jdk/src/share/classes/sun/font/GlyphLayout.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/font/GlyphLayout.java	Wed Jul 05 16:50:32 2017 +0200
@@ -338,6 +338,8 @@
                     cache = new ConcurrentHashMap<SDKey, SDCache>(10);
                     cacheRef = new
                        SoftReference<ConcurrentHashMap<SDKey, SDCache>>(cache);
+                } else if (cache.size() >= 512) {
+                    cache.clear();
                 }
                 cache.put(key, res);
             }
--- a/jdk/src/share/classes/sun/font/StrikeCache.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/font/StrikeCache.java	Wed Jul 05 16:50:32 2017 +0200
@@ -232,6 +232,16 @@
             if (disposer.pScalerContext != 0L) {
                 freeLongMemory(new long[0], disposer.pScalerContext);
             }
+        } else if (disposer.pScalerContext != 0L) {
+            /* Rarely a strike may have been created that never cached
+             * any glyphs. In this case we still want to free the scaler
+             * context.
+             */
+            if (FontManager.longAddresses) {
+                freeLongMemory(new long[0], disposer.pScalerContext);
+            } else {
+                freeIntMemory(new int[0], disposer.pScalerContext);
+            }
         }
     }
 
--- a/jdk/src/share/classes/sun/java2d/cmm/ProfileActivator.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/ProfileActivator.java	Wed Jul 05 16:50:32 2017 +0200
@@ -25,6 +25,7 @@
 
 package sun.java2d.cmm;
 
+import java.awt.color.ProfileDataException;
 
 /**
  * An interface to allow the ProfileDeferralMgr to activate a
@@ -35,6 +36,6 @@
     /**
      * Activate a previously deferred ICC_Profile object.
      */
-    public void activate();
+    public void activate() throws ProfileDataException;
 
 }
--- a/jdk/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java	Wed Jul 05 16:50:32 2017 +0200
@@ -25,6 +25,7 @@
 
 package sun.java2d.cmm;
 
+import java.awt.color.ProfileDataException;
 import java.util.Vector;
 
 
@@ -39,7 +40,7 @@
 public class ProfileDeferralMgr {
 
     public static boolean deferring = true;
-    private static Vector aVector;
+    private static Vector<ProfileActivator> aVector;
 
     /**
      * Records a ProfileActivator object whose activate method will
@@ -51,7 +52,7 @@
             return;
         }
         if (aVector == null) {
-            aVector = new Vector(3, 3);
+            aVector = new Vector<ProfileActivator>(3, 3);
         }
         aVector.addElement(pa);
         return;
@@ -89,8 +90,26 @@
             return;
         }
         n = aVector.size();
-        for (i = 0; i < n; i++) {
-            ((ProfileActivator) aVector.get(i)).activate();
+        for (ProfileActivator pa : aVector) {
+            try {
+                pa.activate();
+            } catch (ProfileDataException e) {
+                /*
+                 * Ignore profile activation error for now:
+                 * such exception is pssible due to absence
+                 * or corruption of standard color profile.
+                 * As for now we expect all profiles should
+                 * be shiped with jre and presence of this
+                 * exception is indication of some configuration
+                 * problem in jre installation.
+                 *
+                 * NB: we still are greedy loading deferred profiles
+                 * and load them all if any of them is needed.
+                 * Therefore broken profile (if any) might be never used.
+                 * If there will be attempt to use broken profile then
+                 * it will result in CMMException.
+                 */
+            }
         }
         aVector.removeAllElements();
         aVector = null;
--- a/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Wed Jul 05 16:50:32 2017 +0200
@@ -120,7 +120,7 @@
 
         // Normalize so 0 <= phase < dash[0]
         int idx = 0;
-        dashOn = false;
+        dashOn = true;
         int d;
         while (phase >= (d = dash[idx])) {
             phase -= d;
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Wed Jul 05 16:50:32 2017 +0200
@@ -245,6 +245,7 @@
                              FloatToS15_16(coords[1]));
                 break;
             case PathIterator.SEG_CLOSE:
+                lsink.lineJoin();
                 lsink.close();
                 break;
             default:
--- a/jdk/src/share/classes/sun/print/ServiceDialog.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 16:50:32 2017 +0200
@@ -2149,55 +2149,51 @@
                         }
                     }
                 }
-
-                rbPortrait.setEnabled(pSupported);
-                rbLandscape.setEnabled(lSupported);
-                rbRevPortrait.setEnabled(rpSupported);
-                rbRevLandscape.setEnabled(rlSupported);
-
-                OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
-                if (or == null ||
-                    !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
-
-                    or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
-                    // need to validate if default is not supported
-                    if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
-                        or = null;
-                        values =
-                            psCurrent.getSupportedAttributeValues(orCategory,
-                                                                  docFlavor,
-                                                                  asCurrent);
-                        if (values instanceof OrientationRequested[]) {
-                            OrientationRequested[] orValues =
-                                                (OrientationRequested[])values;
-                            if (orValues.length > 1) {
-                                // get the first in the list
-                                or = orValues[0];
-                            }
+            }
+
+
+            rbPortrait.setEnabled(pSupported);
+            rbLandscape.setEnabled(lSupported);
+            rbRevPortrait.setEnabled(rpSupported);
+            rbRevLandscape.setEnabled(rlSupported);
+
+            OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
+            if (or == null ||
+                !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
+
+                or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
+                // need to validate if default is not supported
+                if ((or != null) &&
+                   !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
+                    or = null;
+                    Object values =
+                        psCurrent.getSupportedAttributeValues(orCategory,
+                                                              docFlavor,
+                                                              asCurrent);
+                    if (values instanceof OrientationRequested[]) {
+                        OrientationRequested[] orValues =
+                                            (OrientationRequested[])values;
+                        if (orValues.length > 1) {
+                            // get the first in the list
+                            or = orValues[0];
                         }
                     }
-
-                    if (or == null) {
-                        or = OrientationRequested.PORTRAIT;
-                    }
-                    asCurrent.add(or);
+                }
+
+                if (or == null) {
+                    or = OrientationRequested.PORTRAIT;
                 }
-
-                if (or == OrientationRequested.PORTRAIT) {
-                    rbPortrait.setSelected(true);
-                } else if (or == OrientationRequested.LANDSCAPE) {
-                    rbLandscape.setSelected(true);
-                } else if (or == OrientationRequested.REVERSE_PORTRAIT) {
-                    rbRevPortrait.setSelected(true);
-                } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
-                    rbRevLandscape.setSelected(true);
-                }
-                } else {
-                rbPortrait.setEnabled(pSupported);
-                rbLandscape.setEnabled(lSupported);
-                rbRevPortrait.setEnabled(rpSupported);
-                rbRevLandscape.setEnabled(rlSupported);
-
+                asCurrent.add(or);
+            }
+
+            if (or == OrientationRequested.PORTRAIT) {
+                rbPortrait.setSelected(true);
+            } else if (or == OrientationRequested.LANDSCAPE) {
+                rbLandscape.setSelected(true);
+            } else if (or == OrientationRequested.REVERSE_PORTRAIT) {
+                rbRevPortrait.setSelected(true);
+            } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
+                rbRevLandscape.setSelected(true);
             }
         }
     }
--- a/jdk/src/share/native/sun/awt/image/dither.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/awt/image/dither.c	Wed Jul 05 16:50:32 2017 +0200
@@ -169,6 +169,7 @@
     int cubesize = cube_dim * cube_dim * cube_dim;
     unsigned char *useFlags;
     unsigned char *newILut = (unsigned char*)malloc(cubesize);
+    int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);
     if (newILut) {
 
       useFlags = (unsigned char *)calloc(cubesize, 1);
@@ -188,7 +189,7 @@
         currentState.iLUT           = newILut;
 
         currentState.rgb = (unsigned short *)
-                                malloc(256 * sizeof(unsigned short));
+                                malloc(cmap_len * sizeof(unsigned short));
         if (currentState.rgb == NULL) {
             free(newILut);
             free(useFlags);
@@ -199,7 +200,7 @@
         }
 
         currentState.indices = (unsigned char *)
-                                malloc(256 * sizeof(unsigned char));
+                                malloc(cmap_len * sizeof(unsigned char));
         if (currentState.indices == NULL) {
             free(currentState.rgb);
             free(newILut);
@@ -210,18 +211,18 @@
             return NULL;
         }
 
-        for (i = 0; i < 128; i++) {
+        for (i = 0; i < cmap_mid; i++) {
             unsigned short rgb;
             int pixel = cmap[i];
             rgb = (pixel & 0x00f80000) >> 9;
             rgb |= (pixel & 0x0000f800) >> 6;
             rgb |=  (pixel & 0xf8) >> 3;
             INSERTNEW(currentState, rgb, i);
-            pixel = cmap[255-i];
+            pixel = cmap[cmap_len - i - 1];
             rgb = (pixel & 0x00f80000) >> 9;
             rgb |= (pixel & 0x0000f800) >> 6;
             rgb |=  (pixel & 0xf8) >> 3;
-            INSERTNEW(currentState, rgb, 255-i);
+            INSERTNEW(currentState, rgb, cmap_len - i - 1);
         }
 
         if (!recurseLevel(&currentState)) {
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 16:50:32 2017 +0200
@@ -396,7 +396,7 @@
     data->jpegObj = cinfo;
     cinfo->client_data = data;
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("new structures: data is %p, cinfo is %p\n", data, cinfo);
 #endif
 
@@ -673,7 +673,7 @@
     j_decompress_ptr decomp;
 
     qlen = (*env)->GetArrayLength(env, qtables);
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
 #endif
     for (i = 0; i < qlen; i++) {
@@ -876,7 +876,7 @@
         return FALSE;
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("Filling input buffer, remaining skip is %ld, ",
            sb->remaining_skip);
     printf("Buffer length is %d\n", sb->bufferLength);
@@ -906,7 +906,7 @@
             cinfo->err->error_exit((j_common_ptr) cinfo);
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("Buffer filled. ret = %d\n", ret);
 #endif
     /*
@@ -917,7 +917,7 @@
      */
     if (ret <= 0) {
         jobject reader = data->imageIOobj;
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("YO! Early EOI! ret = %d\n", ret);
 #endif
         RELEASE_ARRAYS(env, data, src->next_input_byte);
@@ -1216,21 +1216,24 @@
 {
     jpeg_saved_marker_ptr marker;
     int num_markers = 0;
+    int num_found_markers = 0;
     int seq_no;
     JOCTET *icc_data;
+    JOCTET *dst_ptr;
     unsigned int total_length;
 #define MAX_SEQ_NO  255         // sufficient since marker numbers are bytes
-    char marker_present[MAX_SEQ_NO+1];    // 1 if marker found
-    unsigned int data_length[MAX_SEQ_NO+1]; // size of profile data in marker
-    unsigned int data_offset[MAX_SEQ_NO+1]; // offset for data in marker
+    jpeg_saved_marker_ptr icc_markers[MAX_SEQ_NO + 1];
+    int first;         // index of the first marker in the icc_markers array
+    int last;          // index of the last marker in the icc_markers array
     jbyteArray data = NULL;
 
     /* This first pass over the saved markers discovers whether there are
      * any ICC markers and verifies the consistency of the marker numbering.
      */
 
-    for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
-        marker_present[seq_no] = 0;
+    for (seq_no = 0; seq_no <= MAX_SEQ_NO; seq_no++)
+        icc_markers[seq_no] = NULL;
+
 
     for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
         if (marker_is_icc(marker)) {
@@ -1242,37 +1245,58 @@
                 return NULL;
             }
             seq_no = GETJOCTET(marker->data[12]);
-            if (seq_no <= 0 || seq_no > num_markers) {
+
+            /* Some third-party tools produce images with profile chunk
+             * numeration started from zero. It is inconsistent with ICC
+             * spec, but seems to be recognized by majority of image
+             * processing tools, so we should be more tolerant to this
+             * departure from the spec.
+             */
+            if (seq_no < 0 || seq_no > num_markers) {
                 JNU_ThrowByName(env, "javax/imageio/IIOException",
                      "Invalid icc profile: bad sequence number");
                 return NULL;
             }
-            if (marker_present[seq_no]) {
+            if (icc_markers[seq_no] != NULL) {
                 JNU_ThrowByName(env, "javax/imageio/IIOException",
                      "Invalid icc profile: duplicate sequence numbers");
                 return NULL;
             }
-            marker_present[seq_no] = 1;
-            data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
+            icc_markers[seq_no] = marker;
+            num_found_markers ++;
         }
     }
 
     if (num_markers == 0)
         return NULL;  // There is no profile
 
-    /* Check for missing markers, count total space needed,
-     * compute offset of each marker's part of the data.
+    if (num_markers != num_found_markers) {
+        JNU_ThrowByName(env, "javax/imageio/IIOException",
+                        "Invalid icc profile: invalid number of icc markers");
+        return NULL;
+    }
+
+    first = icc_markers[0] ? 0 : 1;
+    last = num_found_markers + first;
+
+    /* Check for missing markers, count total space needed.
      */
-
     total_length = 0;
-    for (seq_no = 1; seq_no <= num_markers; seq_no++) {
-        if (marker_present[seq_no] == 0) {
+    for (seq_no = first; seq_no < last; seq_no++) {
+        unsigned int length;
+        if (icc_markers[seq_no] == NULL) {
             JNU_ThrowByName(env, "javax/imageio/IIOException",
                  "Invalid icc profile: missing sequence number");
             return NULL;
         }
-        data_offset[seq_no] = total_length;
-        total_length += data_length[seq_no];
+        /* check the data length correctness */
+        length = icc_markers[seq_no]->data_length;
+        if (ICC_OVERHEAD_LEN > length || length > MAX_BYTES_IN_MARKER) {
+            JNU_ThrowByName(env, "javax/imageio/IIOException",
+                 "Invalid icc profile: invalid data length");
+            return NULL;
+        }
+        total_length += (length - ICC_OVERHEAD_LEN);
     }
 
     if (total_length <= 0) {
@@ -1301,19 +1325,14 @@
     }
 
     /* and fill it in */
-    for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
-        if (marker_is_icc(marker)) {
-            JOCTET FAR *src_ptr;
-            JOCTET *dst_ptr;
-            unsigned int length;
-            seq_no = GETJOCTET(marker->data[12]);
-            dst_ptr = icc_data + data_offset[seq_no];
-            src_ptr = marker->data + ICC_OVERHEAD_LEN;
-            length = data_length[seq_no];
-            while (length--) {
-                *dst_ptr++ = *src_ptr++;
-            }
-        }
+    dst_ptr = icc_data;
+    for (seq_no = first; seq_no < last; seq_no++) {
+        JOCTET FAR *src_ptr = icc_markers[seq_no]->data + ICC_OVERHEAD_LEN;
+        unsigned int length =
+            icc_markers[seq_no]->data_length - ICC_OVERHEAD_LEN;
+
+        memcpy(dst_ptr, src_ptr, length);
+        dst_ptr += length;
     }
 
     /* finally, unpin the array */
@@ -1530,6 +1549,7 @@
     j_decompress_ptr cinfo;
     struct jpeg_source_mgr *src;
     sun_jpeg_error_ptr jerr;
+    jbyteArray profileData = NULL;
 
     if (data == NULL) {
         JNU_ThrowByName(env,
@@ -1557,7 +1577,7 @@
         return retval;
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("In readImageHeader, data is %p cinfo is %p\n", data, cinfo);
     printf("clearFirst is %d\n", clearFirst);
 #endif
@@ -1584,7 +1604,7 @@
     if (ret == JPEG_HEADER_TABLES_ONLY) {
         retval = JNI_TRUE;
         imageio_term_source(cinfo);  // Pushback remaining buffer contents
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
         printf("just read tables-only image; q table 0 at %p\n",
                cinfo->quant_tbl_ptrs[0]);
 #endif
@@ -1691,6 +1711,14 @@
             }
         }
         RELEASE_ARRAYS(env, data, src->next_input_byte);
+
+        /* read icc profile data */
+        profileData = read_icc_profile(env, cinfo);
+
+        if ((*env)->ExceptionCheck(env)) {
+            return retval;
+        }
+
         (*env)->CallVoidMethod(env, this,
                                JPEGImageReader_setImageDataID,
                                cinfo->image_width,
@@ -1698,7 +1726,7 @@
                                cinfo->jpeg_color_space,
                                cinfo->out_color_space,
                                cinfo->num_components,
-                               read_icc_profile(env, cinfo));
+                               profileData);
         if (reset) {
             jpeg_abort_decompress(cinfo);
         }
@@ -1827,7 +1855,7 @@
 
     (*env)->ReleaseIntArrayElements(env, srcBands, body, JNI_ABORT);
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("---- in reader.read ----\n");
     printf("numBands is %d\n", numBands);
     printf("bands array: ");
@@ -2487,7 +2515,7 @@
 
     data->streamBuf.suspendable = FALSE;
     if (qtables != NULL) {
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
         printf("in writeTables: qtables not NULL\n");
 #endif
         setQTables(env, (j_common_ptr) cinfo, qtables, TRUE);
@@ -2763,7 +2791,7 @@
 
     cinfo->restart_interval = restartInterval;
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("writer setup complete, starting compressor\n");
 #endif
 
@@ -2812,13 +2840,13 @@
             for (i = 0; i < numBands; i++) {
                 if (scale !=NULL && scale[i] != NULL) {
                     *out++ = scale[i][*(in+i)];
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
                     if (in == data->pixelBuf.buf.bp){ // Just the first pixel
                         printf("in %d -> out %d, ", *(in+i), *(out-i-1));
                     }
 #endif
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
                     if (in == data->pixelBuf.buf.bp){ // Just the first pixel
                         printf("\n");
                     }
--- a/jdk/src/share/native/sun/font/freetypeScaler.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c	Wed Jul 05 16:50:32 2017 +0200
@@ -394,12 +394,14 @@
     scalerInfo->env = env;
     scalerInfo->font2D = font2D;
 
-    FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
+    if (context != NULL) {
+        FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
 
-    errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);
+        errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);
 
-    if (errCode == 0) {
-        errCode = FT_Activate_Size(scalerInfo->face->size);
+        if (errCode == 0) {
+            errCode = FT_Activate_Size(scalerInfo->face->size);
+        }
     }
 
     return errCode;
@@ -885,6 +887,14 @@
         JNIEnv *env, jobject scaler, jlong pScaler) {
     FTScalerInfo* scalerInfo = (FTScalerInfo *) jlong_to_ptr(pScaler);
 
+    /* Freetype functions *may* cause callback to java
+       that can use cached values. Make sure our cache is up to date.
+       NB: scaler context is not important at this point, can use NULL. */
+    int errCode = setupFTContext(env, scaler, scalerInfo, NULL);
+    if (errCode) {
+        return;
+    }
+
     freeNativeResources(env, scalerInfo);
 }
 
@@ -932,12 +942,21 @@
         JNIEnv *env, jobject scaler, jlong pScaler, jchar charCode) {
 
     FTScalerInfo* scalerInfo = (FTScalerInfo *) jlong_to_ptr(pScaler);
+    int errCode;
 
     if (scaler == NULL || scalerInfo->face == NULL) { /* bad/null scaler */
         invalidateJavaScaler(env, scaler, scalerInfo);
         return 0;
     }
 
+    /* Freetype functions *may* cause callback to java
+       that can use cached values. Make sure our cache is up to date.
+       Scaler context is not important here, can use NULL. */
+    errCode = setupFTContext(env, scaler, scalerInfo, NULL);
+    if (errCode) {
+        return 0;
+    }
+
     return FT_Get_Char_Index(scalerInfo->face, charCode);
 }
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Wed Jul 05 16:50:32 2017 +0200
@@ -30,6 +30,41 @@
 #include "Disposer.h"
 #include "lcms.h"
 
+
+#define ALIGNLONG(x) (((x)+3) & ~(3))         // Aligns to DWORD boundary
+
+#ifdef USE_BIG_ENDIAN
+#define AdjustEndianess32(a)
+#else
+
+static
+void AdjustEndianess32(LPBYTE pByte)
+{
+    BYTE temp1;
+    BYTE temp2;
+
+    temp1 = *pByte++;
+    temp2 = *pByte++;
+    *(pByte-1) = *pByte;
+    *pByte++ = temp2;
+    *(pByte-3) = *pByte;
+    *pByte = temp1;
+}
+
+#endif
+
+// Transports to properly encoded values - note that icc profiles does use
+// big endian notation.
+
+static
+icInt32Number TransportValue32(icInt32Number Value)
+{
+    icInt32Number Temp = Value;
+
+    AdjustEndianess32((LPBYTE) &Temp);
+    return Temp;
+}
+
 #define SigMake(a,b,c,d) \
                     ( ( ((int) ((unsigned char) (a))) << 24) | \
                       ( ((int) ((unsigned char) (b))) << 16) | \
@@ -182,6 +217,8 @@
 
     sProf.pf = cmsOpenProfileFromMem((LPVOID)dataArray, (DWORD) dataSize);
 
+    (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
+
     if (sProf.pf == NULL) {
         JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
     }
@@ -337,6 +374,10 @@
     return;
 }
 
+// Modify data for a tag in a profile
+LCMSBOOL LCMSEXPORT _cmsModifyTagData(cmsHPROFILE hProfile,
+                                 icTagSignature sig, void *data, size_t size);
+
 /*
  * Class:     sun_java2d_cmm_lcms_LCMS
  * Method:    setTagData
@@ -345,7 +386,23 @@
 JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
   (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
 {
-    fprintf(stderr, "setTagData operation is not implemented");
+    cmsHPROFILE profile;
+    storeID_t sProf;
+    jbyte* dataArray;
+    int tagSize;
+
+    if (tagSig == SigHead) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_setTagData on icSigHead not "
+                      "permitted");
+        return;
+    }
+
+    sProf.j = id;
+    profile = (cmsHPROFILE) sProf.pf;
+    dataArray = (*env)->GetByteArrayElements(env, data, 0);
+    tagSize =(*env)->GetArrayLength(env, data);
+    _cmsModifyTagData(profile, (icTagSignature) tagSig, dataArray, tagSize);
+    (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
 }
 
 void* getILData (JNIEnv *env, jobject img, jint* pDataType,
@@ -507,3 +564,174 @@
 
     PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
 }
+
+LCMSBOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig,
+                       void *data, size_t size)
+{
+    LCMSBOOL isNew;
+    int i, idx, delta, count;
+    LPBYTE padChars[3] = {0, 0, 0};
+    LPBYTE beforeBuf, afterBuf, ptr;
+    size_t beforeSize, afterSize;
+    icUInt32Number profileSize, temp;
+    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
+
+    isNew = FALSE;
+    idx = _cmsSearchTag(Icc, sig, FALSE);
+    if (idx < 0) {
+        isNew = TRUE;
+        idx = Icc->TagCount++;
+        if (Icc->TagCount >= MAX_TABLE_TAG) {
+            J2dRlsTraceLn1(J2D_TRACE_ERROR, "_cmsModifyTagData: Too many tags "
+                           "(%d)\n", Icc->TagCount);
+            Icc->TagCount = MAX_TABLE_TAG-1;
+            return FALSE;
+        }
+    }
+
+    /* Read in size from header */
+    Icc->Seek(Icc, 0);
+    Icc->Read(&profileSize, sizeof(icUInt32Number), 1, Icc);
+    AdjustEndianess32((LPBYTE) &profileSize);
+
+    /* Compute the change in profile size */
+    if (isNew) {
+        delta = sizeof(icTag) + ALIGNLONG(size);
+    } else {
+        delta = ALIGNLONG(size) - ALIGNLONG(Icc->TagSizes[idx]);
+    }
+    /* Add tag to internal structures */
+    ptr = malloc(size);
+    if (ptr == NULL) {
+        if(isNew) {
+            Icc->TagCount--;
+        }
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "_cmsModifyTagData: ptr == NULL");
+        return FALSE;
+    }
+
+    if (!Icc->Grow(Icc, delta)) {
+        free(ptr);
+        if(isNew) {
+            Icc->TagCount--;
+        }
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "_cmsModifyTagData: Icc->Grow() == FALSE");
+        return FALSE;
+    }
+
+    /* Compute size of tag data before/after the modified tag */
+    beforeSize = ((isNew)?profileSize:Icc->TagOffsets[idx]) -
+                 Icc->TagOffsets[0];
+    if (Icc->TagCount == (idx + 1)) {
+        afterSize = 0;
+    } else {
+        afterSize = profileSize - Icc->TagOffsets[idx+1];
+    }
+    /* Make copies of the data before/after the modified tag */
+    if (beforeSize > 0) {
+        beforeBuf = malloc(beforeSize);
+        if (!beforeBuf) {
+            if(isNew) {
+                Icc->TagCount--;
+            }
+            free(ptr);
+            J2dRlsTraceLn(J2D_TRACE_ERROR,
+                          "_cmsModifyTagData: beforeBuf == NULL");
+            return FALSE;
+        }
+        Icc->Seek(Icc, Icc->TagOffsets[0]);
+        Icc->Read(beforeBuf, beforeSize, 1, Icc);
+    }
+
+    if (afterSize > 0) {
+        afterBuf = malloc(afterSize);
+        if (!afterBuf) {
+            free(ptr);
+            if(isNew) {
+                Icc->TagCount--;
+            }
+            if (beforeSize > 0) {
+                free(beforeBuf);
+            }
+            J2dRlsTraceLn(J2D_TRACE_ERROR,
+                          "_cmsModifyTagData: afterBuf == NULL");
+            return FALSE;
+        }
+        Icc->Seek(Icc, Icc->TagOffsets[idx+1]);
+        Icc->Read(afterBuf, afterSize, 1, Icc);
+    }
+
+    CopyMemory(ptr, data, size);
+    Icc->TagSizes[idx] = size;
+    Icc->TagNames[idx] = sig;
+    if (Icc->TagPtrs[idx]) {
+        free(Icc->TagPtrs[idx]);
+    }
+    Icc->TagPtrs[idx] = ptr;
+    if (isNew) {
+        Icc->TagOffsets[idx] = profileSize;
+    }
+
+
+    /* Update the profile size in the header */
+    profileSize += delta;
+    Icc->Seek(Icc, 0);
+    temp = TransportValue32(profileSize);
+    Icc->Write(Icc, sizeof(icUInt32Number), &temp);
+
+
+    /* Adjust tag offsets: if the tag is new, we must account
+       for the new tag table entry; otherwise, only those tags after
+       the modified tag are changed (by delta) */
+    if (isNew) {
+        for (i = 0; i < Icc->TagCount; ++i) {
+            Icc->TagOffsets[i] += sizeof(icTag);
+        }
+    } else {
+        for (i = idx+1; i < Icc->TagCount; ++i) {
+            Icc->TagOffsets[i] += delta;
+        }
+    }
+
+    /* Write out a new tag table */
+    count = 0;
+    for (i = 0; i < Icc->TagCount; ++i) {
+        if (Icc->TagNames[i] != 0) {
+            ++count;
+        }
+    }
+    Icc->Seek(Icc, sizeof(icHeader));
+    temp = TransportValue32(count);
+    Icc->Write(Icc, sizeof(icUInt32Number), &temp);
+
+    for (i = 0; i < Icc->TagCount; ++i) {
+        if (Icc->TagNames[i] != 0) {
+            icTag tag;
+            tag.sig = TransportValue32(Icc->TagNames[i]);
+            tag.offset = TransportValue32((icInt32Number) Icc->TagOffsets[i]);
+            tag.size = TransportValue32((icInt32Number) Icc->TagSizes[i]);
+            Icc->Write(Icc, sizeof(icTag), &tag);
+        }
+    }
+
+    /* Write unchanged data before the modified tag */
+    if (beforeSize > 0) {
+        Icc->Write(Icc, beforeSize, beforeBuf);
+        free(beforeBuf);
+    }
+
+    /* Write modified tag data */
+    Icc->Write(Icc, size, data);
+    if (size % 4) {
+        Icc->Write(Icc, 4 - (size % 4), padChars);
+    }
+
+    /* Write unchanged data after the modified tag */
+    if (afterSize > 0) {
+        Icc->Write(Icc, afterSize, afterBuf);
+        free(afterBuf);
+    }
+
+    return TRUE;
+}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -51,7 +51,7 @@
 
 
 
-// CIECAM 02 appearance model
+// CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging.
 
 #include "lcms.h"
 
@@ -196,6 +196,10 @@
             clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1;
         }
     }
+
+    clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
+        (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
+
     return clr;
 }
 
@@ -249,9 +253,6 @@
         clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp);
     }
 
-    clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
-        (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
-
     clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A),
         (pMod->c * pMod->z));
 
@@ -395,7 +396,7 @@
     LPcmsCIECAM02 lpMod;
 
 
-   if((lpMod = (LPcmsCIECAM02) malloc(sizeof(cmsCIECAM02))) == NULL) {
+   if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) {
         return (LCMSHANDLE) NULL;
     }
 
@@ -449,14 +450,19 @@
     lpMod -> z   = compute_z(lpMod);
     lpMod -> Nbb = computeNbb(lpMod);
     lpMod -> FL  = computeFL(lpMod);
+
+    if (lpMod -> D == D_CALCULATE ||
+        lpMod -> D == D_CALCULATE_DISCOUNT) {
+
     lpMod -> D   = computeD(lpMod);
+    }
+
     lpMod -> Ncb = lpMod -> Nbb;
 
     lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite);
     lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod);
     lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
     lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
-    lpMod -> adoptedWhite = ComputeCorrelates(lpMod -> adoptedWhite, lpMod);
 
     return (LCMSHANDLE) lpMod;
 
@@ -465,7 +471,7 @@
 void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel)
 {
     LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
-    if (lpMod) free(lpMod);
+    if (lpMod) _cmsFree(lpMod);
 }
 
 
@@ -510,3 +516,4 @@
     pOut ->Z = clr.XYZ[2];
 
 }
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -174,7 +174,7 @@
 LCMSAPI void LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel)
 {
     LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel;
-    if (lpMod) free(lpMod);
+    if (lpMod) _cmsFree(lpMod);
 }
 
 // Partial discounting for adaptation degree computation
@@ -331,7 +331,7 @@
     LPcmsCIECAM97s lpMod;
     VEC3 tmp;
 
-    if((lpMod = (LPcmsCIECAM97s) malloc(sizeof(cmsCIECAM97s))) == NULL) {
+    if((lpMod = (LPcmsCIECAM97s) _cmsMalloc(sizeof(cmsCIECAM97s))) == NULL) {
         return (LCMSHANDLE) NULL;
     }
 
@@ -449,7 +449,7 @@
 
     // RGB_subw = [MlamRigg][WP/YWp]
 #ifdef USE_CIECAM97s2
-    MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, (LPVEC3) &lpMod -> WP);
+    MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &lpMod -> WP);
 #else
     VEC3divK(&tmp, (LPVEC3) &lpMod -> WP, lpMod->WP.Y);
     MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &tmp);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -65,22 +65,25 @@
 // Persistence
 LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
 LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
 
 // Properties
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
-
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
-
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
+
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
+
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
 LCMSAPI double          LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
-LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames);
+LCMSAPI const char*     LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
+LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames);
+LCMSAPI int             LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
 
 // Datasets
 
@@ -89,10 +92,10 @@
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
 LCMSAPI double          LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int col, int row);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
                                                 const char* Val);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
                                                 double Val);
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
@@ -100,15 +103,15 @@
 
 LCMSAPI double          LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
                                                 const char* cSample,
                                                 const char *Val);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
                                                 const char* cSample,
                                                 double Val);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
 LCMSAPI int             LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
 
 LCMSAPI void            LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
@@ -126,7 +129,7 @@
 // #define STRICT_CGATS  1
 
 #define MAXID       128     // Max lenght of identifier
-#define MAXSTR      255     // Max lenght of string
+#define MAXSTR      1024     // Max lenght of string
 #define MAXTABLES   255     // Max Number of tables in a single stream
 #define MAXINCLUDE   20     // Max number of nested includes
 
@@ -137,6 +140,9 @@
 
 #ifndef NON_WINDOWS
 #include <io.h>
+#define DIR_CHAR    '\\'
+#else
+#define DIR_CHAR    '/'
 #endif
 
 // Symbols
@@ -160,6 +166,7 @@
         SEND_DATA,
         SEND_DATA_FORMAT,
         SKEYWORD,
+        SDATA_FORMAT_ID,
         SINCLUDE
 
     } SYMBOL;
@@ -171,7 +178,8 @@
         WRITE_UNCOOKED,
         WRITE_STRINGIFY,
         WRITE_HEXADECIMAL,
-        WRITE_BINARY
+        WRITE_BINARY,
+        WRITE_PAIR
 
     } WRITEMODE;
 
@@ -181,6 +189,8 @@
 
         struct _KeyVal*  Next;
         char*            Keyword;       // Name of variable
+        struct _KeyVal*  NextSubkey;    // If key is a dictionary, points to the next item
+        char*            Subkey;        // If key is a dictionary, points to the subkey name
         char*            Value;         // Points to value
         WRITEMODE        WriteAs;       // How to write the value
 
@@ -220,7 +230,12 @@
 
     } TABLE, *LPTABLE;
 
-
+// File stream being parsed
+
+typedef struct _FileContext {
+        char           FileName[MAX_PATH];    // File name if being readed from file
+        FILE*          Stream;                // File stream or NULL if holded in memory
+    } FILECTX, *LPFILECTX;
 
 // This struct hold all information about an openened
 // IT8 handler. Only one dataset is allowed.
@@ -257,9 +272,9 @@
         char*          Source;                // Points to loc. being parsed
         int            lineno;                // line counter for error reporting
 
-        char           FileName[MAX_PATH];    // File name if being readed from file
-        FILE*          Stream[MAXINCLUDE];    // File stream or NULL if holded in memory
+        LPFILECTX      FileStack[MAXINCLUDE]; // Stack of files being parsed
         int            IncludeSP;             // Include Stack Pointer
+
         char*          MemoryBlock;           // The stream if holded in memory
 
         char           DoubleFormatter[MAXID];   // Printf-like 'double' formatter
@@ -270,14 +285,14 @@
 
 typedef struct {
 
-                FILE* stream;   // For save-to-file behaviour
-
-                LPBYTE Base;
-                LPBYTE Ptr;             // For save-to-mem behaviour
-                size_t Used;
-                size_t Max;
-
-        } SAVESTREAM, FAR* LPSAVESTREAM;
+        FILE* stream;   // For save-to-file behaviour
+
+        LPBYTE Base;
+        LPBYTE Ptr;     // For save-to-mem behaviour
+        size_t Used;
+        size_t Max;
+
+    } SAVESTREAM, FAR* LPSAVESTREAM;
 
 
 // ------------------------------------------------------ IT8 parsing routines
@@ -298,59 +313,104 @@
         {".INCLUDE",            SINCLUDE},
         {"BEGIN_DATA",          SBEGIN_DATA },
         {"BEGIN_DATA_FORMAT",   SBEGIN_DATA_FORMAT },
+        {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID},
         {"END_DATA",            SEND_DATA},
         {"END_DATA_FORMAT",     SEND_DATA_FORMAT},
         {"KEYWORD",             SKEYWORD}
-
         };
 
 #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
 
 // Predefined properties
 
-static const char* PredefinedProperties[] = {
-
-        "NUMBER_OF_FIELDS",    // Required - NUMBER OF FIELDS
-        "NUMBER_OF_SETS",      // Required - NUMBER OF SETS
-        "ORIGINATOR",          // Required - Identifies the specific system, organization or individual that created the data file.
-        "FILE_DESCRIPTOR",     // Required - Describes the purpose or contents of the data file.
-        "CREATED",             // Required - Indicates date of creation of the data file.
-        "DESCRIPTOR",          // Required  - Describes the purpose or contents of the data file.
-        "DIFFUSE_GEOMETRY",    // The diffuse geometry used. Allowed values are "sphere" or "opal".
-        "MANUFACTURER",
-        "MANUFACTURE",         // Some broken Fuji targets does store this value
-        "PROD_DATE",           // Identifies year and month of production of the target in the form yyyy:mm.
-        "SERIAL",              // Uniquely identifies individual physical target.
-
-        "MATERIAL",            // Identifies the material on which the target was produced using a code
+// A property
+typedef struct {
+        const char *id;
+        WRITEMODE as;
+    } PROPERTY;
+
+static PROPERTY PredefinedProperties[] = {
+
+        {"NUMBER_OF_FIELDS", WRITE_UNCOOKED},    // Required - NUMBER OF FIELDS
+        {"NUMBER_OF_SETS",   WRITE_UNCOOKED},    // Required - NUMBER OF SETS
+        {"ORIGINATOR",       WRITE_STRINGIFY},   // Required - Identifies the specific system, organization or individual that created the data file.
+        {"FILE_DESCRIPTOR",  WRITE_STRINGIFY},   // Required - Describes the purpose or contents of the data file.
+        {"CREATED",          WRITE_STRINGIFY},   // Required - Indicates date of creation of the data file.
+        {"DESCRIPTOR",       WRITE_STRINGIFY},   // Required  - Describes the purpose or contents of the data file.
+        {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY},   // The diffuse geometry used. Allowed values are "sphere" or "opal".
+        {"MANUFACTURER",     WRITE_STRINGIFY},
+        {"MANUFACTURE",      WRITE_STRINGIFY},   // Some broken Fuji targets does store this value
+        {"PROD_DATE",        WRITE_STRINGIFY},   // Identifies year and month of production of the target in the form yyyy:mm.
+        {"SERIAL",           WRITE_STRINGIFY},   // Uniquely identifies individual physical target.
+
+        {"MATERIAL",         WRITE_STRINGIFY},   // Identifies the material on which the target was produced using a code
                                // uniquely identifying th e material. This is intend ed to be used for IT8.7
                                // physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
 
-        "INSTRUMENTATION",     // Used to report the specific instrumentation used (manufacturer and
+        {"INSTRUMENTATION",  WRITE_STRINGIFY},   // Used to report the specific instrumentation used (manufacturer and
                                // model number) to generate the data reported. This data will often
                                // provide more information about the particular data collected than an
                                // extensive list of specific details. This is particularly important for
                                // spectral data or data derived from spectrophotometry.
 
-        "MEASUREMENT_SOURCE",  // Illumination used for spectral measurements. This data helps provide
+        {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide
                                // a guide to the potential for issues of paper fluorescence, etc.
 
-        "PRINT_CONDITIONS",    // Used to define the characteristics of the printed sheet being reported.
+        {"PRINT_CONDITIONS", WRITE_STRINGIFY},   // Used to define the characteristics of the printed sheet being reported.
                                // Where standard conditions have been defined (e.g., SWOP at nominal)
                                // named conditions may suffice. Otherwise, detailed information is
                                // needed.
 
-        "SAMPLE_BACKING",      // Identifies the backing material used behind the sample during
-                               // measurement. Allowed values are “black”, “white”, or "na".
-
-        "CHISQ_DOF"            // Degrees of freedom associated with the Chi squared statistic
+        {"SAMPLE_BACKING",   WRITE_STRINGIFY},   // Identifies the backing material used behind the sample during
+                               // measurement. Allowed values are “black”, “white”, or {"na".
+
+        {"CHISQ_DOF",        WRITE_STRINGIFY},   // Degrees of freedom associated with the Chi squared statistic
+
+//    new in recent specs:
+        {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
+                               // along with details of the geometry and the aperture size and shape. For example,
+                               // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
+                               // opal or integrating sphere, etc. For reflection it is important to identify 0/45,
+                               // 45/0, sphere (specular included or excluded), etc.
+
+       {"FILTER",            WRITE_STRINGIFY},   // Identifies the use of physical filter(s) during measurement. Typically used to
+                               // denote the use of filters such as none, D65, Red, Green or Blue.
+
+       {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed
+                               // values are {"yes”, “white”, “none” or “na”.
+
+       {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the
+                               // calculation of various data parameters (2 degree and 10 degree), CIE standard
+                               // illuminant functions used in the calculation of various data parameters (e.g., D50,
+                               // D65, etc.), density status response, etc. If used there shall be at least one
+                               // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
+                               // in the set shall be {"name" and shall identify the particular parameter used.
+                               // The second shall be {"value" and shall provide the value associated with that name.
+                               // For ASCII data, a string containing the Name and Value attribute pairs shall follow
+                               // the weighting function keyword. A semi-colon separates attribute pairs from each
+                               // other and within the attribute the name and value are separated by a comma.
+
+       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name
+                               // of the calculation, parameter is the name of the parameter used in the calculation
+                               // and value is the value of the parameter.
+
+       {"TARGET_TYPE",        WRITE_STRINGIFY},  // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
+
+       {"COLORANT",           WRITE_STRINGIFY},  // Identifies the colorant(s) used in creating the target.
+
+       {"TABLE_DESCRIPTOR",   WRITE_STRINGIFY},  // Describes the purpose or contents of a data table.
+
+       {"TABLE_NAME",         WRITE_STRINGIFY}   // Provides a short name for a data table.
 };
 
-#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(char *))
+#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY))
 
 
 // Predefined sample types on dataset
 static const char* PredefinedSampleID[] = {
+        "SAMPLE_ID",      // Identifies sample that data represents
+        "STRING",         // Identifies label, or other non-machine readable value.
+                          // Value must begin and end with a " symbol
 
         "CMYK_C",         // Cyan component of CMYK data expressed as a percentage
         "CMYK_M",         // Magenta component of CMYK data expressed as a percentage
@@ -378,7 +438,7 @@
         "LAB_B",          // b* component of Lab data
         "LAB_C",          // C*ab component of Lab data
         "LAB_H",          // hab component of Lab data
-        "LAB_DE"          //  CIE dE
+        "LAB_DE",         //  CIE dE
         "LAB_DE_94",      //  CIE dE using CIE 94
         "LAB_DE_CMC",     //  dE using CMC
         "LAB_DE_2000",    // CIE dE using CIE DE 2000
@@ -388,7 +448,7 @@
         "STDEV_Y",        // Standard deviation of Y (tristimulus data)
         "STDEV_Z",        // Standard deviation of Z (tristimulus data)
         "STDEV_L",        // Standard deviation of L*
-        "STDEV_A"         // Standard deviation of a*
+        "STDEV_A",        // Standard deviation of a*
         "STDEV_B",        // Standard deviation of b*
         "STDEV_DE",       // Standard deviation of CIE dE
         "CHI_SQD_PAR"};   // The average of the standard deviations of L*, a* and b*. It is
@@ -397,57 +457,120 @@
 
 #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
 
+//Forward declaration of some internal functions
+static
+void* AllocChunk(LPIT8 it8, size_t size);
+
 // Checks if c is a separator
 static
-BOOL isseparator(int c)
+LCMSBOOL isseparator(int c)
 {
         return (c == ' ') || (c == '\t') || (c == '\r');
 }
 
 // Checks whatever if c is a valid identifier char
-
 static
-BOOL ismiddle(int c)
+LCMSBOOL ismiddle(int c)
 {
    return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
 }
 
 // Checks whatsever if c is a valid identifier middle char.
 static
-BOOL isidchar(int c)
+LCMSBOOL isidchar(int c)
 {
    return isalnum(c) || ismiddle(c);
 }
 
 // Checks whatsever if c is a valid identifier first char.
 static
-BOOL isfirstidchar(int c)
+LCMSBOOL isfirstidchar(int c)
 {
      return !isdigit(c) && ismiddle(c);
 }
 
+// checks whether the supplied path looks like an absolute path
+// NOTE: this function doesn't checks if the path exists or even if it's legal
+static
+LCMSBOOL isabsolutepath(const char *path)
+{
+    if(path == NULL)
+        return FALSE;
+
+    if(path[0] == DIR_CHAR)
+        return TRUE;
+
+#ifndef NON_WINDOWS
+    if(isalpha(path[0]) && path[1] == ':')
+        return TRUE;
+#endif
+    return FALSE;
+}
+
+// Makes a file path based on a given reference path
+// NOTE: buffer is assumed to point to at least MAX_PATH bytes
+// NOTE: both relPath and basePath are assumed to be no more than MAX_PATH characters long (including the null terminator!)
+// NOTE: this function doesn't check if the path exists or even if it's legal
+static
+LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer)
+{
+    if (!isabsolutepath(relPath)) {
+
+        char *tail;
+
+        strncpy(buffer, basePath, MAX_PATH-1);
+        tail = strrchr(buffer, DIR_CHAR);
+        if (tail != NULL) {
+
+            size_t len = tail - buffer;
+            strncpy(tail + 1, relPath, MAX_PATH - len -1);
+            //  TODO: if combined path is longer than MAX_PATH, this should return FALSE!
+            return TRUE;
+        }
+    }
+    strncpy(buffer, relPath, MAX_PATH - 1);
+        buffer[MAX_PATH-1] = 0;
+    return TRUE;
+}
+
+
+// Make sure no exploit is being even tried
 
 static
-BOOL SynError(LPIT8 it8, const char *Txt, ...)
+const char* NoMeta(const char* str)
+{
+    if (strchr(str, '%') != NULL)
+        return "**** CORRUPTED FORMAT STRING ***";
+
+    return str;
+}
+
+
+// Syntax error
+static
+LCMSBOOL SynError(LPIT8 it8, const char *Txt, ...)
 {
         char Buffer[256], ErrMsg[1024];
         va_list args;
 
         va_start(args, Txt);
-        vsprintf(Buffer, Txt, args);
+        vsnprintf(Buffer, 255, Txt, args);
+        Buffer[255] = 0;
         va_end(args);
 
-        sprintf(ErrMsg, "%s: Line %d, %s", it8->FileName, it8->lineno, Buffer);
+        snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer);
+        ErrMsg[1023] = 0;
         it8->sy = SSYNERROR;
-        cmsSignalError(LCMS_ERRC_ABORTED, ErrMsg);
+        cmsSignalError(LCMS_ERRC_ABORTED, "%s", ErrMsg);
         return FALSE;
 }
 
+// Check if current symbol is same as specified. issue an error else.
 static
-BOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
+LCMSBOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
 {
         if (it8 -> sy != sy)
-                return SynError(it8, Err);
+                return SynError(it8, NoMeta(Err));
         return TRUE;
 }
 
@@ -457,15 +580,15 @@
 static
 void NextCh(LPIT8 it8)
 {
-    if (it8 -> Stream[it8 ->IncludeSP]) {
-
-        it8 ->ch = fgetc(it8 ->Stream[it8 ->IncludeSP]);
-
-        if (feof(it8 -> Stream[it8 ->IncludeSP]))  {
+    if (it8 -> FileStack[it8 ->IncludeSP]->Stream) {
+
+        it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream);
+
+        if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream))  {
 
             if (it8 ->IncludeSP > 0) {
 
-                fclose(it8 ->Stream[it8->IncludeSP--]);
+                fclose(it8 ->FileStack[it8->IncludeSP--]->Stream);
                 it8 -> ch = ' ';                            // Whitespace to be ignored
 
             } else
@@ -476,7 +599,6 @@
 
     }
     else {
-
         it8->ch = *it8->Source;
         if (it8->ch) it8->Source++;
     }
@@ -799,18 +921,39 @@
 
     if (it8 -> sy == SINCLUDE) {
 
-                FILE* IncludeFile;
+                LPFILECTX FileNest;
+
+                if(it8 -> IncludeSP >= (MAXINCLUDE-1))
+                {
+                    SynError(it8, "Too many recursion levels");
+                    return;
+                }
 
                 InSymbol(it8);
                 if (!Check(it8, SSTRING, "Filename expected")) return;
-                IncludeFile = fopen(it8 -> str, "rt");
-                if (IncludeFile == NULL) {
-
-                        SynError(it8, "File %s not found", it8 ->str);
+
+                FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
+                if(FileNest == NULL)
+                {
+                    FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
+                    //if(FileNest == NULL)
+                        //  TODO: how to manage out-of-memory conditions?
+                }
+
+                if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE)
+                {
+                    SynError(it8, "File path too long");
+                    return;
+                }
+
+                FileNest->Stream = fopen(FileNest->FileName, "rt");
+                if (FileNest->Stream == NULL) {
+
+                        SynError(it8, "File %s not found", FileNest->FileName);
                         return;
                 }
-
-                it8 -> Stream[++it8 -> IncludeSP] = IncludeFile;
+                it8->IncludeSP++;
+
                 it8 ->ch = ' ';
                 InSymbol(it8);
     }
@@ -819,7 +962,7 @@
 
 // Checks end of line separator
 static
-BOOL CheckEOLN(LPIT8 it8)
+LCMSBOOL CheckEOLN(LPIT8 it8)
 {
         if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
         while (it8 -> sy == SEOLN)
@@ -850,21 +993,26 @@
 
 // Returns a string holding current value
 static
-BOOL GetVal(LPIT8 it8, char* Buffer, const char* ErrorTitle)
+LCMSBOOL GetVal(LPIT8 it8, char* Buffer, size_t max, const char* ErrorTitle)
 {
     switch (it8->sy) {
 
-    case SIDENT:  strncpy(Buffer, it8->id, MAXID-1); break;
-    case SINUM:   sprintf(Buffer, "%d", it8 -> inum); break;
-    case SDNUM:   sprintf(Buffer, it8->DoubleFormatter, it8 -> dnum); break;
-    case SSTRING: strncpy(Buffer, it8->str, MAXSTR-1); break;
+    case SIDENT:  strncpy(Buffer, it8->id, max);
+                  Buffer[max-1]=0;
+                  break;
+    case SINUM:   snprintf(Buffer, max, "%d", it8 -> inum); break;
+    case SDNUM:   snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break;
+    case SSTRING: strncpy(Buffer, it8->str, max);
+                  Buffer[max-1] = 0;
+                  break;
 
 
     default:
-         return SynError(it8, ErrorTitle);
+         return SynError(it8, "%s", ErrorTitle);
     }
 
-     return TRUE;
+    Buffer[max] = 0;
+    return TRUE;
 }
 
 // ---------------------------------------------------------- Table
@@ -872,7 +1020,13 @@
 static
 LPTABLE GetTable(LPIT8 it8)
 {
-    return it8 ->Tab + it8 ->nTable;
+   if ((it8 -> nTable >= it8 ->TablesCount) || (it8 -> nTable < 0)) {
+
+           SynError(it8, "Table %d out of sequence", it8 -> nTable);
+           return it8 -> Tab;
+   }
+
+   return it8 ->Tab + it8 ->nTable;
 }
 
 // ---------------------------------------------------------- Memory management
@@ -896,15 +1050,15 @@
         for (p = it8->MemorySink; p != NULL; p = n) {
 
             n = p->Next;
-            if (p->Ptr) free(p->Ptr);
-            free(p);
+            if (p->Ptr) _cmsFree(p->Ptr);
+            _cmsFree(p);
         }
     }
 
     if (it8->MemoryBlock)
-        free(it8->MemoryBlock);
-
-    free(it8);
+        _cmsFree(it8->MemoryBlock);
+
+     _cmsFree(it8);
 }
 
 
@@ -913,16 +1067,16 @@
 void* AllocBigBlock(LPIT8 it8, size_t size)
 {
    LPOWNEDMEM ptr1;
-   void* ptr = malloc(size);
+   void* ptr = _cmsMalloc(size);
 
         if (ptr) {
 
                 ZeroMemory(ptr, size);
-                ptr1 = (LPOWNEDMEM) malloc(sizeof(OWNEDMEM));
+                ptr1 = (LPOWNEDMEM) _cmsMalloc(sizeof(OWNEDMEM));
 
                 if (ptr1 == NULL) {
 
-                    free(ptr);
+                     _cmsFree(ptr);
                     return NULL;
                 }
 
@@ -986,8 +1140,9 @@
 // Searches through linked list
 
 static
-BOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr)
+LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr)
 {
+    if (LastPtr) *LastPtr = p;
 
     for (;  p != NULL; p = p->Next) {
 
@@ -996,8 +1151,22 @@
         if (*Key != '#') { // Comments are ignored
 
             if (stricmp(Key, p->Keyword) == 0)
-                    return TRUE;
+                    break;
+        }
         }
+
+    if (p == NULL)
+        return FALSE;
+
+    if (Subkey == 0)
+        return TRUE;
+
+    for (; p != NULL; p = p->NextSubkey) {
+
+        if (LastPtr) *LastPtr = p;
+
+        if (stricmp(Subkey, p->Subkey) == 0)
+            return TRUE;
     }
 
     return FALSE;
@@ -1007,35 +1176,55 @@
 
 // Add a property into a linked list
 static
-BOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* xValue, WRITEMODE WriteAs)
+LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
 {
     LPKEYVALUE p;
-    LPKEYVALUE last;
-
 
     // Check if property is already in list (this is an error)
 
-    if (IsAvailableOnList(*Head, Key, &last)) {
-
-                        // This may work for editing properties
-
-                         last->Value   = AllocString(it8, xValue);
-                         last->WriteAs = WriteAs;
-                         return TRUE;
-
-             // return SynError(it8, "duplicate key <%s>", Key);
+    if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
+
+            // This may work for editing properties
+
+        //     return SynError(it8, "duplicate key <%s>", Key);
     }
-
-        // Allocate the container
+    else {
+        LPKEYVALUE last = p;
+
+    // Allocate the container
     p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE));
     if (p == NULL)
     {
-        return SynError(it8, "AddToList: out of memory");
+            SynError(it8, "AddToList: out of memory");
+            return NULL;
     }
 
     // Store name and value
     p->Keyword = AllocString(it8, Key);
-
+        p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey);
+
+        // Keep the container in our list
+        if (*Head == NULL)
+            *Head = p;
+        else
+        {
+            if(Subkey != 0 && last != 0) {
+                last->NextSubkey = p;
+
+                // If Subkey is not null, then last is the last property with the same key,
+                // but not necessarily is the last property in the list, so we need to move
+                // to the actual list end
+                while(last->Next != 0)
+                    last = last->Next;
+    }
+            last->Next = p;
+    }
+
+    p->Next    = NULL;
+        p->NextSubkey = NULL;
+    }
+
+    p->WriteAs = WriteAs;
     if (xValue != NULL) {
 
         p->Value   = AllocString(it8, xValue);
@@ -1044,29 +1233,20 @@
         p->Value   = NULL;
     }
 
-    p->Next    = NULL;
-    p->WriteAs = WriteAs;
-
-    // Keep the container in our list
-    if (*Head == NULL)
-        *Head = p;
-    else
-        last->Next = p;
-
-    return TRUE;
+    return p;
 }
 
 static
-BOOL AddAvailableProperty(LPIT8 it8, const char* Key)
+LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as)
 {
-        return AddToList(it8, &it8->ValidKeywords, Key, NULL, WRITE_UNCOOKED);
+        return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
 }
 
 
 static
-BOOL AddAvailableSampleID(LPIT8 it8, const char* Key)
+LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key)
 {
-        return AddToList(it8, &it8->ValidSampleID, Key, NULL, WRITE_UNCOOKED);
+        return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
 }
 
 
@@ -1122,8 +1302,6 @@
     AllocTable(it8);
 
     it8->MemoryBlock = NULL;
-    it8->Stream[0]   = NULL;
-    it8->IncludeSP   = 0;
     it8->MemorySink  = NULL;
 
     it8 ->nTable = 0;
@@ -1141,6 +1319,8 @@
     it8 -> inum = 0;
     it8 -> dnum = 0.0;
 
+    it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
+    it8->IncludeSP   = 0;
     it8 -> lineno = 1;
 
     strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
@@ -1149,7 +1329,7 @@
     // Initialize predefined properties & data
 
     for (i=0; i < NUMPREDEFINEDPROPS; i++)
-            AddAvailableProperty(it8, PredefinedProperties[i]);
+            AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
 
     for (i=0; i < NUMPREDEFINEDSAMPLEID; i++)
             AddAvailableSampleID(it8, PredefinedSampleID[i]);
@@ -1167,65 +1347,72 @@
 
 }
 
-BOOL  LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type)
+LCMSBOOL  LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type)
 {
         LPIT8 it8 = (LPIT8) hIT8;
 
         strncpy(it8 ->SheetType, Type, MAXSTR-1);
+        it8 ->SheetType[MAXSTR-1] = 0;
         return TRUE;
 }
 
-BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
 
     if (!Val) return FALSE;
     if (!*Val) return FALSE;
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, "# ", Val, WRITE_UNCOOKED);
+    return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL;
 }
 
 
 
 // Sets a property
-BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
 
     if (!Val) return FALSE;
     if (!*Val) return FALSE;
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, Key, Val, WRITE_STRINGIFY);
+    return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL;
 }
 
 
-BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
     char Buffer[1024];
 
     sprintf(Buffer, it8->DoubleFormatter, Val);
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_UNCOOKED);
+    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;
 }
 
-BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
     char Buffer[1024];
 
     sprintf(Buffer, "%d", Val);
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_HEXADECIMAL);
+    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
 }
 
-BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
+LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
 {
     LPIT8 it8 = (LPIT8) hIT8;
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, Key, Buffer, WRITE_UNCOOKED);
+    return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
 }
 
+LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
+{
+    LPIT8 it8 = (LPIT8) hIT8;
+
+    return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL;
+}
 
 // Gets a property
 const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key)
@@ -1233,7 +1420,7 @@
     LPIT8 it8 = (LPIT8) hIT8;
     LPKEYVALUE p;
 
-    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, &p))
+    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p))
     {
         return p -> Value;
     }
@@ -1249,6 +1436,18 @@
     else return 0.0;
 }
 
+const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey)
+{
+    LPIT8 it8 = (LPIT8) hIT8;
+    LPKEYVALUE p;
+
+    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p))
+    {
+        return p -> Value;
+    }
+    return NULL;
+}
+
 // ----------------------------------------------------------------- Datasets
 
 
@@ -1287,10 +1486,17 @@
 }
 
 static
-BOOL SetDataFormat(LPIT8 it8, int n, const char *label)
+LCMSBOOL SetDataFormat(LPIT8 it8, int n, const char *label)
 {
     LPTABLE t = GetTable(it8);
 
+#ifdef  STRICT_CGATS
+    if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) {
+        SynError(it8, "Invalid data format '%s'.", label);
+        return FALSE;
+    }
+#endif
+
     if (!t->DataFormat)
         AllocateDataFormat(it8);
 
@@ -1308,7 +1514,7 @@
 }
 
 
-BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample)
+LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample)
 {
         LPIT8 it8 = (LPIT8) h;
         return SetDataFormat(it8, n, Sample);
@@ -1348,7 +1554,7 @@
 }
 
 static
-BOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val)
+LCMSBOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val)
 {
     LPTABLE t = GetTable(it8);
 
@@ -1383,42 +1589,43 @@
 void WriteStr(LPSAVESTREAM f, const char *str)
 {
 
-        size_t len;
-
-        if (str == NULL)
-                str = " ";
-
-        // Lenghth to write
-        len = strlen(str);
+    size_t len;
+
+    if (str == NULL)
+        str = " ";
+
+    // Lenghth to write
+    len = strlen(str);
     f ->Used += len;
 
 
-        if (f ->stream) {       // Should I write it to a file?
-
-                fwrite(str, 1, len, f->stream);
+    if (f ->stream) {   // Should I write it to a file?
+
+        fwrite(str, 1, len, f->stream);
+
+    }
+    else {  // Or to a memory block?
+
+
+        if (f ->Base) {   // Am I just counting the bytes?
+
+            if (f ->Used > f ->Max) {
+
+                cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
+                return;
+            }
+
+            CopyMemory(f ->Ptr, str, len);
+            f->Ptr += len;
 
         }
-        else {  // Or to a memory block?
-
-
-                if (f ->Base) {   // Am I just counting the bytes?
-
-                        if (f ->Used > f ->Max) {
-
-                                cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
-                                return;
-                        }
-
-                        CopyMemory(f ->Ptr, str, len);
-                        f->Ptr += len;
-
-                }
-
-        }
+
+    }
 }
 
 
-//
+// Write formatted
+
 static
 void Writef(LPSAVESTREAM f, const char* frm, ...)
 {
@@ -1426,7 +1633,8 @@
     va_list args;
 
     va_start(args, frm);
-    vsprintf(Buffer, frm, args);
+    vsnprintf(Buffer, 4095, frm, args);
+    Buffer[4095] = 0;
     WriteStr(f, Buffer);
     va_end(args);
 
@@ -1450,7 +1658,7 @@
             for (Pt = p ->Value; *Pt; Pt++) {
 
 
-                                Writef(fp, "%c", *Pt);
+                Writef(fp, "%c", *Pt);
 
                 if (*Pt == '\n') {
                     WriteStr(fp, "# ");
@@ -1462,7 +1670,7 @@
         }
 
 
-        if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL)) {
+        if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
 
 #ifdef STRICT_CGATS
             WriteStr(fp, "KEYWORD\t\"");
@@ -1470,7 +1678,7 @@
             WriteStr(fp, "\"\n");
 #endif
 
-            AddAvailableProperty(it8, p->Keyword);
+            AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
 
         }
 
@@ -1495,6 +1703,10 @@
                     Writef(fp, "\t0x%B", atoi(p ->Value));
                     break;
 
+            case WRITE_PAIR:
+                    Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value);
+                    break;
+
             default: SynError(it8, "Unknown write mode %d", p ->WriteAs);
                      return;
             }
@@ -1573,13 +1785,13 @@
 
 
 // Saves whole file
-BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
+LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
 {
     SAVESTREAM sd;
     int i;
     LPIT8 it8 = (LPIT8) hIT8;
 
-        ZeroMemory(&sd, sizeof(SAVESTREAM));
+    ZeroMemory(&sd, sizeof(SAVESTREAM));
 
     sd.stream = fopen(cFileName, "wt");
     if (!sd.stream) return FALSE;
@@ -1594,31 +1806,31 @@
             WriteData(&sd, it8);
     }
 
-        fclose(sd.stream);
+    fclose(sd.stream);
 
     return TRUE;
 }
 
 
 // Saves to memory
-BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
+LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
 {
     SAVESTREAM sd;
     int i;
     LPIT8 it8 = (LPIT8) hIT8;
 
-        ZeroMemory(&sd, sizeof(SAVESTREAM));
+    ZeroMemory(&sd, sizeof(SAVESTREAM));
 
     sd.stream = NULL;
-        sd.Base   = (LPBYTE) MemPtr;
-        sd.Ptr    = sd.Base;
-
-        sd.Used = 0;
-
-        if (sd.Base)
-                sd.Max  = *BytesNeeded;         // Write to memory?
-        else
-                sd.Max  = 0;                            // Just counting the needed bytes
+    sd.Base   = (LPBYTE) MemPtr;
+    sd.Ptr    = sd.Base;
+
+    sd.Used = 0;
+
+    if (sd.Base)
+        sd.Max  = *BytesNeeded;     // Write to memory?
+    else
+        sd.Max  = 0;                // Just counting the needed bytes
 
     WriteStr(&sd, it8->SheetType);
     WriteStr(&sd, "\n");
@@ -1630,12 +1842,12 @@
             WriteData(&sd, it8);
     }
 
-        sd.Used++;      // The \0 at the very end
-
-        if (sd.Base)
-                sd.Ptr = 0;
-
-        *BytesNeeded = sd.Used;
+    sd.Used++;  // The \0 at the very end
+
+    if (sd.Base)
+        sd.Ptr = 0;
+
+    *BytesNeeded = sd.Used;
 
     return TRUE;
 }
@@ -1644,7 +1856,7 @@
 // -------------------------------------------------------------- Higer level parsing
 
 static
-BOOL DataFormatSection(LPIT8 it8)
+LCMSBOOL DataFormatSection(LPIT8 it8)
 {
     int iField = 0;
     LPTABLE t = GetTable(it8);
@@ -1685,16 +1897,19 @@
 
 
 static
-BOOL DataSection (LPIT8 it8)
+LCMSBOOL DataSection (LPIT8 it8)
 {
     int  iField = 0;
     int  iSet   = 0;
-    char Buffer[256];
+    char Buffer[MAXSTR];
     LPTABLE t = GetTable(it8);
 
     InSymbol(it8);   // Eats "BEGIN_DATA"
     CheckEOLN(it8);
 
+    if (!t->Data)
+        AllocateDataSet(it8);
+
     while (it8->sy != SEND_DATA && it8->sy != SEOF)
     {
         if (iField >= t -> nSamples) {
@@ -1705,7 +1920,7 @@
 
         if (it8->sy != SEND_DATA && it8->sy != SEOF) {
 
-            if (!GetVal(it8, Buffer, "Sample data expected"))
+            if (!GetVal(it8, Buffer, 255, "Sample data expected"))
                 return FALSE;
 
             if (!SetData(it8, iSet, iField, Buffer))
@@ -1734,10 +1949,11 @@
 
 
 static
-BOOL HeaderSection(LPIT8 it8)
+LCMSBOOL HeaderSection(LPIT8 it8)
 {
     char VarName[MAXID];
     char Buffer[MAXSTR];
+    LPKEYVALUE Key;
 
         while (it8->sy != SEOF &&
                it8->sy != SSYNERROR &&
@@ -1749,30 +1965,79 @@
 
         case SKEYWORD:
                 InSymbol(it8);
-                if (!GetVal(it8, Buffer, "Keyword expected")) return FALSE;
-                if (!AddAvailableProperty(it8, Buffer)) return FALSE;
+                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
+                if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE;
+                InSymbol(it8);
+                break;
+
+
+        case SDATA_FORMAT_ID:
+                InSymbol(it8);
+                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
+                if (!AddAvailableSampleID(it8, Buffer)) return FALSE;
                 InSymbol(it8);
                 break;
 
 
         case SIDENT:
                 strncpy(VarName, it8->id, MAXID-1);
-
-                if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL)) {
+                VarName[MAXID-1] = 0;
+
+                if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
 
 #ifdef STRICT_CGATS
                  return SynError(it8, "Undefined keyword '%s'", VarName);
 #else
-                if (!AddAvailableProperty(it8, VarName)) return FALSE;
+                    Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
+                    if (Key == NULL) return FALSE;
 #endif
                 }
 
                 InSymbol(it8);
-                if (!GetVal(it8, Buffer, "Property data expected")) return FALSE;
-
-
-                AddToList(it8, &GetTable(it8)->HeaderList, VarName, Buffer,
-                                                                (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
+                if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
+
+                if(Key->WriteAs != WRITE_PAIR) {
+                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+                                (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
+                }
+                else {
+                    const char *Subkey;
+                    char *Nextkey;
+                    if (it8->sy != SSTRING)
+                        return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
+
+                    // chop the string as a list of "subkey, value" pairs, using ';' as a separator
+                    for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
+                    {
+                        char *Value, *temp;
+
+                        //  identify token pair boundary
+                        Nextkey = (char*) strchr(Subkey, ';');
+                        if(Nextkey)
+                            *Nextkey++ = '\0';
+
+                        // for each pair, split the subkey and the value
+                        Value = (char*) strrchr(Subkey, ',');
+                        if(Value == NULL)
+                            return SynError(it8, "Invalid value for property '%s'.", VarName);
+
+                        // gobble the spaces before the coma, and the coma itself
+                        temp = Value++;
+                        do *temp-- = '\0'; while(temp >= Subkey && *temp == ' ');
+
+                        // gobble any space at the right
+                        temp = Value + strlen(Value) - 1;
+                        while(*temp == ' ') *temp-- = '\0';
+
+                        // trim the strings from the left
+                        Subkey += strspn(Subkey, " ");
+                        Value += strspn(Value, " ");
+
+                        if(Subkey[0] == 0 || Value[0] == 0)
+                            return SynError(it8, "Invalid value for property '%s'.", VarName);
+                        AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
+                    }
+                }
 
                 InSymbol(it8);
                 break;
@@ -1793,22 +2058,23 @@
 
 
 static
-BOOL ParseIT8(LPIT8 it8)
+LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet)
 {
-    char* SheetTypePtr;
+    char* SheetTypePtr = it8 ->SheetType;
+
+    if (nosheet == 0) {
 
     // First line is a very special case.
 
     while (isseparator(it8->ch))
             NextCh(it8);
 
-    SheetTypePtr = it8 ->SheetType;
-
     while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
 
         *SheetTypePtr++= (char) it8 ->ch;
         NextCh(it8);
     }
+    }
 
     *SheetTypePtr = 0;
     InSymbol(it8);
@@ -1869,6 +2135,12 @@
 
     for (idField = 0; idField < t -> nSamples; idField++)
     {
+        if (t ->DataFormat == NULL) {
+             SynError(it8, "Undefined DATA_FORMAT");
+             return;
+
+        }
+
         Fld = t->DataFormat[idField];
         if (!Fld) continue;
 
@@ -1884,6 +2156,7 @@
                     char Buffer[256];
 
                     strncpy(Buffer, Data, 255);
+                    Buffer[255] = 0;
 
                     if (strlen(Buffer) <= strlen(Data))
                         strcpy(Data, Buffer);
@@ -1916,7 +2189,7 @@
                                     LPTABLE Table = it8 ->Tab + k;
                                     LPKEYVALUE p;
 
-                                    if (IsAvailableOnList(Table->HeaderList, Label, &p)) {
+                                    if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
 
                                         // Available, keep type and table
                                         char Buffer[256];
@@ -1924,7 +2197,7 @@
                                         char *Type  = p ->Value;
                                         int  nTable = k;
 
-                                        sprintf(Buffer, "%s %d %s", Label, nTable, Type );
+                                        snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
 
                                         SetData(it8, i, idField, Buffer);
                                     }
@@ -1948,8 +2221,9 @@
 // that should be something like some printable characters plus a \n
 
 static
-BOOL IsMyBlock(LPBYTE Buffer, size_t n)
+int IsMyBlock(LPBYTE Buffer, size_t n)
 {
+    int cols = 1, space = 0, quot = 0;
     size_t i;
 
     if (n < 10) return FALSE;   // Too small
@@ -1959,9 +2233,26 @@
 
     for (i = 1; i < n; i++) {
 
-        if (Buffer[i] == '\n' || Buffer[i] == '\r' || Buffer[i] == '\t') return TRUE;
-        if (Buffer[i] < 32) return FALSE;
-
+        switch(Buffer[i])
+        {
+        case '\n':
+        case '\r':
+            return quot == 1 || cols > 2 ? 0 : cols;
+        case '\t':
+        case ' ':
+            if(!quot && !space)
+                space = 1;
+            break;
+        case '\"':
+            quot = !quot;
+            break;
+        default:
+            if (Buffer[i] < 32) return 0;
+            if (Buffer[i] > 127) return 0;
+            cols += space;
+            space = 0;
+            break;
+        }
     }
 
     return FALSE;
@@ -1970,7 +2261,7 @@
 
 
 static
-BOOL IsMyFile(const char* FileName)
+int IsMyFile(const char* FileName)
 {
    FILE *fp;
    size_t Size;
@@ -1998,21 +2289,22 @@
     LCMSHANDLE hIT8;
     LPIT8  it8;
 
-    if (!IsMyBlock((LPBYTE) Ptr, len)) return NULL;
+    int type = IsMyBlock((LPBYTE) Ptr, len);
+    if (type == 0) return NULL;
 
     hIT8 = cmsIT8Alloc();
     if (!hIT8) return NULL;
 
     it8 = (LPIT8) hIT8;
-    it8 ->MemoryBlock = (char*) malloc(len + 1);
+    it8 ->MemoryBlock = (char*) _cmsMalloc(len + 1);
 
     strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
     it8 ->MemoryBlock[len] = 0;
 
-    strncpy(it8->FileName, "", MAX_PATH-1);
+    strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1);
     it8-> Source = it8 -> MemoryBlock;
 
-    if (!ParseIT8(it8)) {
+    if (!ParseIT8(it8, type-1)) {
 
         cmsIT8Free(hIT8);
         return FALSE;
@@ -2021,7 +2313,7 @@
     CookPointers(it8);
     it8 ->nTable = 0;
 
-    free(it8->MemoryBlock);
+     _cmsFree(it8->MemoryBlock);
     it8 -> MemoryBlock = NULL;
 
     return hIT8;
@@ -2036,26 +2328,28 @@
      LCMSHANDLE hIT8;
      LPIT8  it8;
 
-     if (!IsMyFile(cFileName)) return NULL;
+     int type = IsMyFile(cFileName);
+     if (type == 0) return NULL;
 
      hIT8 = cmsIT8Alloc();
      it8 = (LPIT8) hIT8;
      if (!hIT8) return NULL;
 
 
-     it8 ->Stream[0] = fopen(cFileName, "rt");
-
-     if (!it8 ->Stream[0]) {
+     it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
+
+     if (!it8 ->FileStack[0]->Stream) {
          cmsIT8Free(hIT8);
          return NULL;
      }
 
 
-    strncpy(it8->FileName, cFileName, MAX_PATH-1);
-
-    if (!ParseIT8(it8)) {
-
-            fclose(it8 ->Stream[0]);
+    strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1);
+    it8->FileStack[0]->FileName[MAX_PATH-1] = 0;
+
+    if (!ParseIT8(it8, type-1)) {
+
+            fclose(it8 ->FileStack[0]->Stream);
             cmsIT8Free(hIT8);
             return NULL;
     }
@@ -2063,7 +2357,7 @@
     CookPointers(it8);
     it8 ->nTable = 0;
 
-    fclose(it8 ->Stream[0]);
+    fclose(it8 ->FileStack[0]->Stream);
     return hIT8;
 
 }
@@ -2078,12 +2372,12 @@
 }
 
 
-int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames)
+int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames)
 {
     LPIT8 it8 = (LPIT8) hIT8;
     LPKEYVALUE p;
     int n;
-    char **Props;
+    const char **Props;
     LPTABLE t = GetTable(it8);
 
     // Pass#1 - count properties
@@ -2094,7 +2388,7 @@
     }
 
 
-    Props = (char **) AllocChunk(it8, sizeof(char *) * n);
+    Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
 
     // Pass#2 - Fill pointers
     n = 0;
@@ -2106,6 +2400,41 @@
     return n;
 }
 
+int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
+{
+    LPIT8 it8 = (LPIT8) hIT8;
+    LPKEYVALUE p, tmp;
+    int n;
+    const char **Props;
+    LPTABLE t = GetTable(it8);
+
+    if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
+        *SubpropertyNames = 0;
+        return 0;
+    }
+
+    // Pass#1 - count properties
+
+    n = 0;
+    for (tmp = p;  tmp != NULL; tmp = tmp->NextSubkey) {
+        if(tmp->Subkey != NULL)
+            n++;
+    }
+
+
+    Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
+
+    // Pass#2 - Fill pointers
+    n = 0;
+    for (tmp = p;  tmp != NULL; tmp = tmp->NextSubkey) {
+        if(tmp->Subkey != NULL)
+            Props[n++] = p ->Subkey;
+    }
+
+    *SubpropertyNames = Props;
+    return n;
+}
+
 static
 int LocatePatch(LPIT8 it8, const char* cPatch)
 {
@@ -2201,7 +2530,7 @@
 }
 
 
-BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
 
@@ -2209,7 +2538,7 @@
 }
 
 
-BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val)
+LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
     char Buff[256];
@@ -2260,7 +2589,7 @@
 
 
 
-BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
+LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
                         const char* cSample,
                         const char *Val)
 {
@@ -2305,18 +2634,19 @@
 }
 
 
-BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
+LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
                         const char* cSample,
                         double Val)
 {
     LPIT8 it8 = (LPIT8) hIT8;
     char Buff[256];
 
-        sprintf(Buff, it8->DoubleFormatter, Val);
+        snprintf(Buff, 255, it8->DoubleFormatter, Val);
         return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
 
 }
 
+// Buffer should get MAXSTR at least
 
 const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer)
 {
@@ -2327,10 +2657,16 @@
         if (!Data) return NULL;
         if (!buffer) return Data;
 
-        strcpy(buffer, Data);
+        strncpy(buffer, Data, MAXSTR-1);
+        buffer[MAXSTR-1] = 0;
         return buffer;
 }
 
+int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch)
+{
+    return LocatePatch((LPIT8)hIT8, cPatch);
+}
+
 int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8)
 {
         LPIT8 it8 = (LPIT8) hIT8;
@@ -2356,7 +2692,7 @@
     cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
     if (!cLabelFld) return -1;
 
-    if (sscanf(cLabelFld, "%s %d %s", Label, &nTable, Type) != 3)
+    if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3)
             return -1;
 
     if (ExpectedType != NULL && *ExpectedType == 0)
@@ -2371,6 +2707,19 @@
 }
 
 
+LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample)
+{
+    LPIT8 it8 = (LPIT8) hIT8;
+
+    int pos = LocateSample(it8, cSample);
+    if(pos == -1)
+        return FALSE;
+
+    it8->Tab[it8->nTable].SampleID = pos;
+    return TRUE;
+}
+
+
 void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter)
 {
     LPIT8 it8 = (LPIT8) hIT8;
@@ -2380,3 +2729,4 @@
     else
         strcpy(it8->DoubleFormatter, Formatter);
 }
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -256,7 +256,7 @@
 // Return TRUE if both m and of are empy -- "m" being identity and "of" being 0
 
 static
-BOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of)
+LCMSBOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of)
 {
     WVEC3 wv0;
 
@@ -661,3 +661,6 @@
 
        return rc;
 }
+
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -57,6 +57,7 @@
 // errors.
 
 void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...);
+
 int  LCMSEXPORT cmsErrorAction(int lAbort);
 void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn);
 
@@ -96,7 +97,7 @@
 
             char Buffer[1024];
 
-            vsprintf(Buffer, ErrorText, args);
+            vsnprintf(Buffer, 1023, ErrorText, args);
             va_end(args);
 
             if (UserErrorHandler(ErrorCode, Buffer)) {
@@ -118,8 +119,8 @@
               char Buffer1[1024];
               char Buffer2[256];
 
-              sprintf(Buffer1, "Error #%x; ", ErrorCode);
-              vsprintf(Buffer2, ErrorText, args);
+              snprintf(Buffer1,  767, "Error #%x; ", ErrorCode);
+              vsnprintf(Buffer2, 255, ErrorText, args);
               strcat(Buffer1, Buffer2);
               MessageBox(NULL, Buffer1, "Little cms",
                                           MB_OK|MB_ICONSTOP|MB_TASKMODAL);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -63,9 +63,9 @@
 LPGAMMATABLE LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[]);
 LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma);
 LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints);
-BOOL         LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
+LCMSBOOL         LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
 
-BOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints);
+LCMSBOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints);
 
 
 // Sampled curves
@@ -74,7 +74,7 @@
 void           cdecl cmsFreeSampledCurve(LPSAMPLEDCURVE p);
 void           cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
 void           cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
-BOOL           cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
+LCMSBOOL       cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
 void           cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
 
 LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
@@ -84,7 +84,6 @@
 
 // ----------------------------------------------------------------------------------------
 
-// #define DEBUG 1
 
 #define MAX_KNOTS   4096
 typedef float vec[MAX_KNOTS+1];
@@ -144,14 +143,14 @@
        LPGAMMATABLE p;
        size_t size;
 
-       if (nEntries > 65530) {
-                cmsSignalError(LCMS_ERRC_WARNING, "Couldn't create gammatable of more than 65530 entries; 65530 assumed");
-                nEntries = 65530;
+       if (nEntries > 65530 || nEntries <= 0) {
+                cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't create gammatable of more than 65530 entries");
+                return NULL;
        }
 
        size = sizeof(GAMMATABLE) + (sizeof(WORD) * (nEntries-1));
 
-       p = (LPGAMMATABLE) malloc(size);
+       p = (LPGAMMATABLE) _cmsMalloc(size);
        if (!p) return NULL;
 
        ZeroMemory(p, size);
@@ -164,7 +163,7 @@
 
 void LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma)
 {
-       if (Gamma) free(Gamma);
+       if (Gamma)  _cmsFree(Gamma);
 }
 
 
@@ -278,6 +277,15 @@
        LPWORD InPtr;
        LPGAMMATABLE p;
 
+       // Try to reverse it analytically whatever possible
+       if (InGamma -> Seed.Type > 0 && InGamma -> Seed.Type <= 5 &&
+            _cmsCrc32OfGammaTable(InGamma) == InGamma -> Seed.Crc32) {
+
+                return cmsBuildParametricGamma(nResultSamples, -(InGamma -> Seed.Type), InGamma ->Seed.Params);
+       }
+
+
+       // Nope, reverse the table
        p = cmsAllocGamma(nResultSamples);
        if (!p) return NULL;
 
@@ -528,7 +536,7 @@
 
 // Smooths a curve sampled at regular intervals
 
-BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda)
+LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda)
 
 {
     vec w, y, z;
@@ -640,13 +648,13 @@
 {
     LPSAMPLEDCURVE pOut;
 
-    pOut = (LPSAMPLEDCURVE) malloc(sizeof(SAMPLEDCURVE));
+    pOut = (LPSAMPLEDCURVE) _cmsMalloc(sizeof(SAMPLEDCURVE));
     if (pOut == NULL)
             return NULL;
 
-    if((pOut->Values = (double *) malloc(nItems * sizeof(double))) == NULL)
+    if((pOut->Values = (double *) _cmsMalloc(nItems * sizeof(double))) == NULL)
     {
-        free(pOut);
+         _cmsFree(pOut);
         return NULL;
     }
 
@@ -659,8 +667,8 @@
 
 void cmsFreeSampledCurve(LPSAMPLEDCURVE p)
 {
-    free((LPVOID) p -> Values);
-    free((LPVOID) p);
+     _cmsFree((LPVOID) p -> Values);
+     _cmsFree((LPVOID) p);
 }
 
 
@@ -731,7 +739,7 @@
 
 // Smooths a curve sampled at regular intervals
 
-BOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda)
+LCMSBOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda)
 {
     vec w, y, z;
     int i, nItems;
@@ -915,14 +923,11 @@
 
 // Smooth endpoints (used in Black/White compensation)
 
-BOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries)
+LCMSBOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries)
 {
     vec w, y, z;
     int i, Zeros, Poles;
 
-#ifdef DEBUG
-        ASAVE(Table, nEntries, "nonsmt.txt");
-#endif
 
 
     if (cmsIsLinear(Table, nEntries)) return FALSE; // Nothing to do
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -66,7 +66,7 @@
 */
 
 
-BOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black,
+LCMSBOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black,
                             int *nOutputs)
 {
        // Only most common spaces
@@ -376,7 +376,6 @@
     double bs = Lab2 ->b;
     double Cs = sqrt( Sqr(as) + Sqr(bs) );
 
-
     double G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) ));
 
     double a_p = (1 + G ) * a1;
@@ -390,15 +389,21 @@
     double C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
     double h_ps = atan2deg(a_ps, b_ps);
 
-
-
     double meanC_p =(C_p + C_ps) / 2;
 
-    double meanh_p = fabs(h_ps-h_p) <= 180 ? (h_ps + h_p)/2 : (h_ps+h_p-360)/2;
+    double hps_plus_hp  = h_ps + h_p;
+    double hps_minus_hp = h_ps - h_p;
+
+    double meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
+                            (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
+                                                 (hps_plus_hp - 360)/2;
 
-    double delta_h = fabs(h_p - h_ps) <= 180 ? fabs(h_p - h_ps) : 360 - fabs(h_p - h_ps);
-    double delta_L = fabs(L1 - Ls);
-    double delta_C = fabs(C_p - C_ps);
+    double delta_h = (hps_minus_hp) <= -180.000001 ?  (hps_minus_hp + 360) :
+                            (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
+                                                    (hps_minus_hp);
+    double delta_L = (Ls - L1);
+    double delta_C = (C_ps - C_p );
+
 
     double delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANES(delta_h) / 2);
 
@@ -1065,7 +1070,7 @@
 // Check for monotonicity.
 
 static
-BOOL IsMonotonic(LPGAMMATABLE t)
+LCMSBOOL IsMonotonic(LPGAMMATABLE t)
 {
     int n = t -> nEntries;
     int i, last;
@@ -1088,7 +1093,7 @@
 // Check for endpoints
 
 static
-BOOL HasProperEndpoints(LPGAMMATABLE t)
+LCMSBOOL HasProperEndpoints(LPGAMMATABLE t)
 {
     if (t ->GammaTable[0] != 0) return FALSE;
     if (t ->GammaTable[t ->nEntries-1] != 0xFFFF) return FALSE;
@@ -1109,7 +1114,7 @@
     unsigned int t, i, v;
     int j;
     WORD In[MAXCHANNELS], Out[MAXCHANNELS];
-    BOOL lIsSuitable;
+    LCMSBOOL lIsSuitable;
     _LPcmsTRANSFORM InputXForm   = (_LPcmsTRANSFORM) h[0];
     _LPcmsTRANSFORM OutputXForm  = (_LPcmsTRANSFORM) h[nTransforms-1];
 
@@ -1126,10 +1131,10 @@
     }
 
 
-    // Do nothing on all but RGB to RGB transforms
+    // Do nothing on all but Gray/RGB to Gray/RGB transforms
 
-    if ((InputXForm ->EntryColorSpace != icSigRgbData) ||
-        (OutputXForm->ExitColorSpace  != icSigRgbData)) return;
+    if (((InputXForm ->EntryColorSpace != icSigRgbData) && (InputXForm ->EntryColorSpace != icSigGrayData)) ||
+        ((OutputXForm->ExitColorSpace  != icSigRgbData) && (OutputXForm->ExitColorSpace  != icSigGrayData))) return;
 
 
     for (t = 0; t < Grid -> InputChan; t++)
@@ -1169,10 +1174,13 @@
         if (!HasProperEndpoints(Trans[t]))
                     lIsSuitable = FALSE;
 
+        /*
         // Exclude if transfer function is not smooth enough
         // to be modelled as a gamma function, or the gamma is reversed
+
         if (cmsEstimateGamma(Trans[t]) < 1.0)
                     lIsSuitable = FALSE;
+        */
 
     }
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -282,7 +282,7 @@
 // Fills optimization parameters
 
 void cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
-                                            BOOL lUseTetrahedral, LPL16PARAMS p)
+                                            LCMSBOOL lUseTetrahedral, LPL16PARAMS p)
 {
        int clutPoints;
 
@@ -579,7 +579,7 @@
 
                 // Identify if value fall downto 0 or FFFF zone
                 if (Value == 0) return 0;
-                if (Value == 0xFFFF) return 0xFFFF;
+               // if (Value == 0xFFFF) return 0xFFFF;
 
                 // else restrict to valid zone
 
@@ -631,7 +631,7 @@
         a = (y1 - y0) / (x1 - x0);
         b = y0 - a * x0;
 
-        if (a == 0) return (WORD) x;
+        if (fabs(a) < 0.01) return (WORD) x;
 
         f = ((Value - b) / a);
 
@@ -763,7 +763,7 @@
     X0 = p -> opta3 * x0;
     X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
 
-        Y0 = p -> opta2 * y0;
+    Y0 = p -> opta2 * y0;
     Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
 
     Z0 = p -> opta1 * z0;
@@ -942,7 +942,7 @@
     X0 = p -> opta3 * x0;
     X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
 
-        Y0 = p -> opta2 * y0;
+    Y0 = p -> opta2 * y0;
     Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
 
     Z0 = p -> opta1 * z0;
@@ -1009,11 +1009,11 @@
 
         Rest = c1 * rx + c2 * ry + c3 * rz;
 
-                // There is a lot of math hidden in this expression. The rest is in fixed domain
-                // and the result in 0..ffff domain. So the complete expression should be
-                // ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF
+        // There is a lot of math hidden in this expression. The rest is in fixed domain
+        // and the result in 0..ffff domain. So the complete expression should be
+        // ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF
 
-                Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF));
+        Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF));
 
     }
 
@@ -1131,3 +1131,4 @@
 }
 
 #undef DENS
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -62,7 +62,7 @@
 typedef struct {
                 LPBYTE Block;           // Points to allocated memory
                 size_t Size;            // Size of allocated memory
-                int Pointer;            // Points to current location
+                size_t Pointer;         // Points to current location
                 int FreeBlockOnClose;   // As title
 
                 } FILEMEM;
@@ -70,18 +70,19 @@
 static
 LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode)
 {
-    FILEMEM* fm = (FILEMEM*) malloc(sizeof(FILEMEM));
+    FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM));
+    if (fm == NULL) return NULL;
+
     ZeroMemory(fm, sizeof(FILEMEM));
 
     if (Mode == 'r') {
 
-        fm ->Block   = (LPBYTE) malloc(Size);
+        fm ->Block   = (LPBYTE) _cmsMalloc(Size);
         if (fm ->Block == NULL) {
-            free(fm);
+             _cmsFree(fm);
             return NULL;
         }
 
-
         CopyMemory(fm->Block, Block, Size);
         fm ->FreeBlockOnClose = TRUE;
     }
@@ -103,13 +104,27 @@
      FILEMEM* ResData = (FILEMEM*) Icc ->stream;
      LPBYTE Ptr;
      size_t len = size * count;
+     size_t extent = ResData -> Pointer + len;
 
+        if (len == 0) {
+                return 0;
+        }
 
-     if (ResData -> Pointer + len > ResData -> Size){
+        if (len / size != count) {
+          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size.");
+          return 0;
+      }
+
+      if (extent < len || extent < ResData -> Pointer) {
+          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len.");
+          return 0;
+      }
+
+      if (ResData -> Pointer + len > ResData -> Size) {
 
          len = (ResData -> Size - ResData -> Pointer);
-         cmsSignalError(LCMS_ERRC_WARNING, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
-
+         cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
+         return 0;
      }
 
     Ptr  = ResData -> Block;
@@ -123,7 +138,7 @@
 // SEEK_CUR is assumed
 
 static
-BOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
+LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
 {
     FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 
@@ -147,18 +162,19 @@
 }
 
 
-// Writes data to memory, also keeps used space for further reference
+// Writes data to memory, also keeps used space for further reference. NO CHECK IS PERFORMED
 
 static
-BOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
+LCMSBOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
 {
         FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 
        if (size == 0) return TRUE;
 
        if (ResData != NULL)
-           CopyMemory(ResData ->Block + Icc ->UsedSpace, Ptr, size);
+           CopyMemory(ResData ->Block + ResData ->Pointer, Ptr, size);
 
+       ResData->Pointer += size;
        Icc->UsedSpace += size;
 
        return TRUE;
@@ -166,15 +182,37 @@
 
 
 static
-BOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
+LCMSBOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
+{
+    FILEMEM* ResData = (FILEMEM*) Icc->stream;
+
+    void* newBlock = NULL;
+
+    /* Follow same policies as functions in lcms.h  */
+    if (ResData->Size + size < 0) return NULL;
+    if (ResData->Size + size > ((size_t)1024*1024*500)) return NULL;
+
+    newBlock = realloc(ResData->Block, ResData->Size + size);
+
+    if (!newBlock) {
+        return FALSE;
+    }
+    ResData->Block = newBlock;
+    ResData->Size += size;
+    return TRUE;
+}
+
+
+static
+LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
 {
     FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 
     if (ResData ->FreeBlockOnClose) {
 
-        if (ResData ->Block) free(ResData ->Block);
+        if (ResData ->Block)  _cmsFree(ResData ->Block);
     }
-    free(ResData);
+     _cmsFree(ResData);
     return 0;
 }
 
@@ -192,7 +230,7 @@
 {
     size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream);
     if (nReaded != count) {
-            cmsSignalError(LCMS_ERRC_WARNING, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
+            cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
             return 0;
     }
 
@@ -201,7 +239,7 @@
 
 
 static
-BOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
+LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
 {
     if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) {
 
@@ -223,7 +261,7 @@
 
 
 static
-BOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
+LCMSBOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
 {
        if (size == 0) return TRUE;
 
@@ -239,7 +277,14 @@
 
 
 static
-BOOL FileClose(struct _lcms_iccprofile_struct* Icc)
+LCMSBOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
+{
+  return TRUE;
+}
+
+
+static
+LCMSBOOL FileClose(struct _lcms_iccprofile_struct* Icc)
 {
     return fclose((FILE*) Icc ->stream);
 }
@@ -252,7 +297,7 @@
 cmsHPROFILE _cmsCreateProfilePlaceholder(void)
 {
 
-    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) malloc(sizeof(LCMSICCPROFILE));
+    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE));
     if (Icc == NULL) return NULL;
 
     // Empty values
@@ -290,7 +335,7 @@
 // Search for a specific tag in tag dictionary
 // Returns position or -1 if tag not found
 
-icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError)
+icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError)
 {
        icInt32Number i;
 
@@ -311,7 +356,7 @@
 
 // Check existance
 
-BOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
+LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
 {
        LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
        return _cmsSearchTag(Icc, sig, FALSE) >= 0;
@@ -330,7 +375,7 @@
 
     if (i >=0) {
 
-        if (Icc -> TagPtrs[i]) free(Icc -> TagPtrs[i]);
+        if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]);
     }
     else  {
 
@@ -341,11 +386,14 @@
 
             cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG);
             Icc ->TagCount = MAX_TABLE_TAG-1;
+            return NULL;
         }
     }
 
 
-    Ptr = malloc(size);
+    Ptr = _cmsMalloc(size);
+    if (Ptr == NULL) return NULL;
+
     CopyMemory(Ptr, Init, size);
 
     Icc ->TagNames[i] = sig;
@@ -376,12 +424,15 @@
     if (NewIcc == NULL) return NULL;
 
     strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1);
+    NewIcc -> PhysicalFile[MAX_PATH-1] = 0;
+
     NewIcc ->stream = ICCfile;
 
     NewIcc ->Read  = FileRead;
     NewIcc ->Seek  = FileSeek;
     NewIcc ->Tell  = FileTell;
     NewIcc ->Close = FileClose;
+    NewIcc ->Grow  = FileGrow;
     NewIcc ->Write = NULL;
 
     NewIcc ->IsWrite = FALSE;
@@ -419,7 +470,8 @@
     NewIcc ->Seek  = MemorySeek;
     NewIcc ->Tell  = MemoryTell;
     NewIcc ->Close = MemoryClose;
-    NewIcc ->Write = NULL;
+    NewIcc ->Grow  = MemoryGrow;
+    NewIcc ->Write = MemoryWrite;
 
     NewIcc ->IsWrite = FALSE;
 
@@ -476,7 +528,7 @@
 
 
 
-BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
 {
      LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) hProfile;
      *Dest = Icc -> MediaWhitePoint;
@@ -484,14 +536,14 @@
 }
 
 
-BOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
 {
       LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) hProfile;
       *Dest = Icc -> MediaBlackPoint;
       return TRUE;
 }
 
-BOOL  LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
+LCMSBOOL  LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
 {
        LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
        *Dest = Icc -> Illuminant;
@@ -549,7 +601,7 @@
 }
 
 
-BOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
 {
     LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
     CopyMemory(Dest, &Icc ->Created, sizeof(struct tm));
@@ -570,23 +622,18 @@
        Icc -> PCS = pcs;
 }
 
-
-
 icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile)
 {
        LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
        return Icc -> ColorSpace;
 }
 
-
-
 void LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig)
 {
        LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
        Icc -> ColorSpace = sig;
 }
 
-
 icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile)
 {
        LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
@@ -599,7 +646,6 @@
        return (DWORD) Icc -> Version;
 }
 
-
 void LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version)
 {
    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
@@ -638,7 +684,7 @@
 
 // This is tricky, since LUT structs does have pointers
 
-BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
+LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
 {
        LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
        LPLUT Orig, Stored;
@@ -666,7 +712,7 @@
 }
 
 
-BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
+LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
 {
        LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
@@ -675,7 +721,7 @@
 }
 
 
-BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
+LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
 {
        LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
@@ -683,7 +729,7 @@
        return TRUE;
 }
 
-BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
+LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
@@ -692,7 +738,7 @@
 }
 
 
-BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
+LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
@@ -701,7 +747,7 @@
 }
 
 
-BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
+LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
@@ -711,28 +757,40 @@
 }
 
 
-BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
+LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
     _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
-    return FALSE;
+    return TRUE;
 }
 
 
-BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
+LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
     _cmsInitTag(Icc, sig, sizeof(struct tm), DateTime);
-    return FALSE;
+    return TRUE;
 }
 
 
-BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
+LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 
     _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
-    return FALSE;
+    return TRUE;
 }
+
+
+LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat)
+{
+    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
+
+    _cmsInitTag(Icc, sig, 3*sizeof(cmsCIEXYZ), mat);
+    return TRUE;
+
+}
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -149,6 +149,7 @@
 
 #endif
 
+
 // Transports to properly encoded values - note that icc profiles does use
 // big endian notation.
 
@@ -216,7 +217,8 @@
 {
     icTagBase Base;
 
-    Icc -> Read(&Base, sizeof(icTagBase), 1, Icc);
+    if (Icc -> Read(&Base, sizeof(icTagBase), 1, Icc) != 1)
+                return (icTagTypeSignature) 0;
     AdjustEndianess32((LPBYTE) &Base.sig);
 
     return Base.sig;
@@ -288,13 +290,15 @@
 // Read profile header and validate it
 
 static
-LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
+LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, LCMSBOOL lIsFromMemory)
 {
      icTag Tag;
      icHeader Header;
      icInt32Number TagCount, i;
-
-     Icc -> Read(&Header, sizeof(icHeader), 1, Icc);
+     icUInt32Number extent;
+
+       if (Icc -> Read(&Header, sizeof(icHeader), 1, Icc) != 1)
+                      goto ErrorCleanup;
 
        // Convert endian
 
@@ -306,14 +310,13 @@
        AdjustEndianess32((LPBYTE) &Header.pcs);
        AdjustEndianess32((LPBYTE) &Header.magic);
        AdjustEndianess32((LPBYTE) &Header.flags);
-           AdjustEndianess32((LPBYTE) &Header.attributes[0]);
+       AdjustEndianess32((LPBYTE) &Header.attributes[0]);
        AdjustEndianess32((LPBYTE) &Header.renderingIntent);
 
        // Validate it
 
        if (Header.magic != icMagicNumber) goto ErrorCleanup;
 
-
        if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1)
                      goto ErrorCleanup;
 
@@ -324,7 +327,7 @@
        Icc -> PCS             = Header.pcs;
        Icc -> RenderingIntent = (icRenderingIntent) Header.renderingIntent;
        Icc -> flags           = Header.flags;
-           Icc -> attributes      = Header.attributes[0];
+       Icc -> attributes      = Header.attributes[0];
        Icc -> Illuminant.X    = Convert15Fixed16(Header.illuminant.X);
        Icc -> Illuminant.Y    = Convert15Fixed16(Header.illuminant.Y);
        Icc -> Illuminant.Z    = Convert15Fixed16(Header.illuminant.Z);
@@ -348,7 +351,7 @@
 
        // Read tag directory
 
-       if (TagCount > MAX_TABLE_TAG) {
+       if (TagCount > MAX_TABLE_TAG || TagCount < 0) {
 
            cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount);
            goto ErrorCleanup;
@@ -357,12 +360,18 @@
        Icc -> TagCount = TagCount;
        for (i=0; i < TagCount; i++) {
 
-              Icc ->Read(&Tag, sizeof(icTag), 1, Icc);
+              if (Icc ->Read(&Tag, sizeof(icTag), 1, Icc) != 1)
+                  goto ErrorCleanup;
 
               AdjustEndianess32((LPBYTE) &Tag.offset);
               AdjustEndianess32((LPBYTE) &Tag.size);
               AdjustEndianess32((LPBYTE) &Tag.sig);            // Signature
 
+              // Perform some sanity check. Offset + size should fall inside file.
+              extent = Tag.offset + Tag.size;
+              if (extent > Header.size || extent < Tag.offset)
+                  goto ErrorCleanup;
+
               Icc -> TagNames[i]   = Tag.sig;
               Icc -> TagOffsets[i] = Tag.offset;
               Icc -> TagSizes[i]   = Tag.size;
@@ -381,13 +390,10 @@
              cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile);
 
 
-       free(Icc);
+        _cmsFree(Icc);
        return NULL;
 }
 
-
-
-
 static
 unsigned int uipow(unsigned int a, unsigned int b) {
         unsigned int rv = 1;
@@ -497,7 +503,7 @@
 // The infamous LUT 8
 
 static
-void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
+LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
 {
     icLut8 LUT8;
     LPBYTE Temp;
@@ -506,7 +512,7 @@
     unsigned int AllLinear;
     LPWORD PtrW;
 
-       Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc);
+       if (Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return FALSE;
 
        NewLUT -> wFlags        = LUT_HASTL1|LUT_HASTL2|LUT_HAS3DGRID;
        NewLUT -> cLutPoints    = LUT8.clutPoints;
@@ -515,6 +521,10 @@
        NewLUT -> InputEntries  = 256;
        NewLUT -> OutputEntries = 256;
 
+       // Do some checking
+       if (!_cmsValidateLUT(NewLUT)) {
+          return FALSE;
+       }
 
        AdjustEndianess32((LPBYTE) &LUT8.e00);
        AdjustEndianess32((LPBYTE) &LUT8.e01);
@@ -550,13 +560,24 @@
 
        // Copy input tables
 
-       Temp = (LPBYTE) malloc(256);
+       Temp = (LPBYTE) _cmsMalloc(256);
+       if (Temp == NULL) return FALSE;
+
        AllLinear = 0;
        for (i=0; i < NewLUT -> InputChan; i++) {
 
-              PtrW = (LPWORD) malloc(sizeof(WORD) * 256);
+              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
+              if (PtrW == NULL) {
+                   _cmsFree(Temp);
+                  return FALSE;
+                  }
+
               NewLUT -> L1[i] = PtrW;
-              Icc ->Read(Temp, 1, 256, Icc);
+              if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
+                   _cmsFree(Temp);
+                  return FALSE;
+                  }
+
               for (j=0; j < 256; j++)
                      PtrW[j] = TO16_TAB(Temp[j]);
                      AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
@@ -569,7 +590,7 @@
               NewLUT -> wFlags &= ~LUT_HASTL1;
        }
 
-       free(Temp);
+        _cmsFree(Temp);
 
        // Copy 3D CLUT
 
@@ -578,9 +599,20 @@
 
        if (nTabSize > 0) {
 
-            PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize);
-            Temp = (LPBYTE) malloc(nTabSize);
-            Icc ->Read(Temp, 1, nTabSize, Icc);
+            PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
+            if (PtrW == NULL) return FALSE;
+
+            Temp = (LPBYTE) _cmsMalloc(nTabSize);
+            if (Temp == NULL) {
+                 _cmsFree(PtrW);
+                return FALSE;
+                }
+
+            if (Icc ->Read(Temp, 1, nTabSize, Icc) != nTabSize) {
+                 _cmsFree(Temp);
+                _cmsFree(PtrW);
+                return FALSE;
+                }
 
             NewLUT -> T = PtrW;
             NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
@@ -589,25 +621,37 @@
 
                      *PtrW++ = TO16_TAB(Temp[i]);
             }
-            free(Temp);
+            _cmsFree(Temp);
        }
        else {
            NewLUT ->T = NULL;
            NewLUT ->Tsize = 0;
-           NewLUT -> wFlags &= ~LUT_HAS3DGRID;
+           NewLUT ->wFlags &= ~LUT_HAS3DGRID;
        }
 
 
-
        // Copy output tables
 
-       Temp = (LPBYTE) malloc(256);
+       Temp = (LPBYTE) _cmsMalloc(256);
+       if (Temp == NULL) {
+           return FALSE;
+           }
+
        AllLinear = 0;
        for (i=0; i < NewLUT -> OutputChan; i++) {
 
-              PtrW = (LPWORD) malloc(sizeof(WORD) * 256);
+              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
+              if (PtrW == NULL) {
+                  _cmsFree(Temp);
+                  return FALSE;
+                  }
+
               NewLUT -> L2[i] = PtrW;
-              Icc ->Read(Temp, 1, 256, Icc);
+              if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
+                  _cmsFree(Temp);
+                  return FALSE;
+                  }
+
               for (j=0; j < 256; j++)
                      PtrW[j] = TO16_TAB(Temp[j]);
                      AllLinear += cmsIsLinear(NewLUT -> L2[i], 256);
@@ -621,7 +665,7 @@
        }
 
 
-       free(Temp);
+       _cmsFree(Temp);
 
        cmsCalcL16Params(NewLUT -> InputEntries,  &NewLUT -> In16params);
        cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params);
@@ -646,6 +690,15 @@
            // some profiles does claim to do that. Poor lcms will try
            // to detect such condition and fix up "on the fly".
 
+           switch (sig) {
+
+            case icSigBToA0Tag:
+            case icSigBToA1Tag:
+            case icSigBToA2Tag:
+            case icSigGamutTag:
+            case icSigPreview0Tag:
+            case icSigPreview1Tag:
+            case icSigPreview2Tag:
            {
                LPWORD WhiteLab, ExpectedWhite;
                WORD WhiteFixed[MAXCHANNELS], WhiteUnfixed[MAXCHANNELS];
@@ -685,9 +738,13 @@
                }
 
            }
-
+           break;
+
+        default:;
+        }
        }
 
+       return TRUE;
 }
 
 
@@ -696,7 +753,7 @@
 // Case LUT 16
 
 static
-void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
+LCMSBOOL ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
 {
     icLut16 LUT16;
     size_t nTabSize;
@@ -705,7 +762,8 @@
     LPWORD PtrW;
 
 
-       Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc);
+       if (Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc) != 1)
+            return FALSE;
 
        NewLUT -> wFlags        = LUT_HASTL1 | LUT_HASTL2 | LUT_HAS3DGRID;
        NewLUT -> cLutPoints    = LUT16.clutPoints;
@@ -718,6 +776,9 @@
        NewLUT -> InputEntries  = LUT16.inputEnt;
        NewLUT -> OutputEntries = LUT16.outputEnt;
 
+       if (!_cmsValidateLUT(NewLUT)) {
+         return FALSE;
+       }
 
        // Matrix handling
 
@@ -754,9 +815,14 @@
        AllLinear = 0;
        for (i=0; i < NewLUT -> InputChan; i++) {
 
-              PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries);
+              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
+              if (PtrW == NULL) return FALSE;
+
               NewLUT -> L1[i] = PtrW;
-              Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc);
+              if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc) != NewLUT -> InputEntries) {
+                  return FALSE;
+                  }
+
               AdjustEndianessArray16(PtrW, NewLUT -> InputEntries);
               AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
               }
@@ -775,12 +841,17 @@
                                                 NewLUT->InputChan));
        if (nTabSize > 0) {
 
-           PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize);
+           PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
+           if (PtrW == NULL)
+               return FALSE;
 
            NewLUT -> T = PtrW;
            NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
 
-           Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc);
+           if (Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc) != nTabSize) {
+               return FALSE;
+           }
+
            AdjustEndianessArray16(NewLUT -> T, nTabSize);
        }
        else {
@@ -794,9 +865,16 @@
        AllLinear = 0;
        for (i=0; i < NewLUT -> OutputChan; i++) {
 
-              PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries);
+              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
+              if (PtrW == NULL) {
+                  return FALSE;
+                  }
+
               NewLUT -> L2[i] = PtrW;
-              Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc);
+              if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc) != NewLUT -> OutputEntries) {
+                  return FALSE;
+                  }
+
               AdjustEndianessArray16(PtrW, NewLUT -> OutputEntries);
               AllLinear += cmsIsLinear(NewLUT -> L2[i], NewLUT -> OutputEntries);
               }
@@ -814,6 +892,8 @@
        cmsCalcCLUT16Params(NewLUT -> cLutPoints,  NewLUT -> InputChan,
                                                   NewLUT -> OutputChan,
                                                   &NewLUT -> CLut16params);
+
+       return TRUE;
 }
 
 
@@ -830,17 +910,15 @@
 
 
        BaseType = ReadBase(Icc);
-
        switch (BaseType) {
 
 
-       case 0x9478ee00L:    // Monaco 2 profiler is BROKEN!
+       case ((icTagTypeSignature) 0x9478ee00):    // Monaco 2 profiler is BROKEN!
        case icSigCurveType:
 
-           Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
+           if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
            AdjustEndianess32((LPBYTE) &Count);
 
-
            switch (Count) {
 
            case 0:   // Linear.
@@ -855,7 +933,7 @@
                     {
                      WORD SingleGammaFixed;
 
-                     Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc);
+                     if (Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
                      AdjustEndianess16((LPBYTE) &SingleGammaFixed);
                      return cmsBuildGamma(4096, Convert8Fixed8(SingleGammaFixed));
                      }
@@ -865,10 +943,9 @@
                      NewGamma = cmsAllocGamma(Count);
                      if (!NewGamma) return NULL;
 
-                     Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc);
-
+                     if (Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
+                         return NULL;
                      AdjustEndianessArray16(NewGamma -> GammaTable, Count);
-
                      return NewGamma;
                     }
               }
@@ -885,11 +962,11 @@
            icUInt16Number   Type;
            int i;
 
-           Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc);
-           Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc);
+           if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
+           if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
 
            AdjustEndianess16((LPBYTE) &Type);
-           if (Type > 5) {
+           if (Type > 4) {
 
                 cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
                 return NULL;
@@ -900,7 +977,7 @@
 
           for (i=0; i < n; i++) {
                 Num = 0;
-                Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
+                if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
                 Params[i] = Convert15Fixed16(Num);
           }
 
@@ -938,7 +1015,7 @@
        case 0x9478ee00L:    // Monaco 2 profiler is BROKEN!
        case icSigCurveType:
 
-           Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc);
+           if (Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
            AdjustEndianess32((LPBYTE) &Count);
 
 
@@ -948,6 +1025,7 @@
 
                      NewGamma = cmsAllocGamma(2);
                      if (!NewGamma) return NULL;
+
                      NewGamma -> GammaTable[0] = 0;
                      NewGamma -> GammaTable[1] = 0xFFFF;
                      return NewGamma;
@@ -955,7 +1033,7 @@
            case 1:  {
                      WORD SingleGammaFixed;
 
-                     Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc);
+                     if (Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
                      AdjustEndianess16((LPBYTE) &SingleGammaFixed);
                      return cmsBuildGamma(4096, 1./Convert8Fixed8(SingleGammaFixed));
                      }
@@ -965,7 +1043,8 @@
                      NewGamma = cmsAllocGamma(Count);
                      if (!NewGamma) return NULL;
 
-                     Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc);
+                     if (Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
+                         return NULL;
 
                      AdjustEndianessArray16(NewGamma -> GammaTable, Count);
 
@@ -992,11 +1071,11 @@
            int i;
 
 
-           Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc);
-           Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc);
+           if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
+           if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
 
            AdjustEndianess16((LPBYTE) &Type);
-           if (Type > 5) {
+           if (Type > 4) {
 
                 cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
                 return NULL;
@@ -1006,7 +1085,7 @@
           n = ParamsByType[Type];
 
           for (i=0; i < n; i++) {
-                Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
+                if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
                 Params[i] = Convert15Fixed16(Num);
           }
 
@@ -1028,7 +1107,7 @@
 // V4 stuff. Read matrix for LutAtoB and LutBtoA
 
 static
-BOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags)
+LCMSBOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags)
 {
 
     icS15Fixed16Number All[12];
@@ -1038,7 +1117,8 @@
 
     if (Icc -> Seek(Icc, Offset)) return FALSE;
 
-    Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc);
+    if (Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc) != 12)
+        return FALSE;
 
     for (i=0; i < 12;  i++)
               AdjustEndianess32((LPBYTE) &All[i]);
@@ -1067,17 +1147,26 @@
 //  V4 stuff. Read CLUT part for LutAtoB and LutBtoA
 
 static
-BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
+LCMSBOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
 {
-
+    unsigned int j;
     icCLutStruct CLUT;
 
     if (Icc -> Seek(Icc, Offset)) return FALSE;
-    Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc);
-
-
-    cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan,
-                                               NewLUT ->OutputChan);
+    if (Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc) != 1) return FALSE;
+
+
+    for (j=1; j < NewLUT ->InputChan; j++) {
+        if (CLUT.gridPoints[0] != CLUT.gridPoints[j]) {
+            cmsSignalError(LCMS_ERRC_ABORTED, "CLUT with different granulatity is currently unsupported.");
+            return FALSE;
+        }
+
+
+    }
+
+    if (cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan,
+                                               NewLUT ->OutputChan) == NULL) return FALSE;
 
     // Precission can be 1 or 2 bytes
 
@@ -1087,7 +1176,7 @@
         unsigned int i;
 
         for (i=0; i < NewLUT->Tsize / sizeof(WORD); i++) {
-                Icc ->Read(&v, sizeof(BYTE), 1, Icc);
+                if (Icc ->Read(&v, sizeof(BYTE), 1, Icc) != 1) return FALSE;
                 NewLUT->T[i] = TO16_TAB(v);
         }
 
@@ -1095,10 +1184,10 @@
     else
         if (CLUT.prec == 2) {
 
-         Icc ->Read(NewLUT ->T, sizeof(WORD),
-                    NewLUT->Tsize / sizeof(WORD), Icc);
-
-        AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD));
+         size_t n = NewLUT->Tsize / sizeof(WORD);
+
+         if (Icc ->Read(NewLUT ->T, sizeof(WORD), n, Icc) != n) return FALSE;
+         AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD));
     }
     else {
         cmsSignalError(LCMS_ERRC_ABORTED, "Unknow precission of '%d'", CLUT.prec);
@@ -1110,6 +1199,22 @@
 
 
 static
+void ResampleCurves(LPGAMMATABLE Curves[], int nCurves)
+{
+    int i;
+    LPSAMPLEDCURVE sc;
+
+    for (i=0; i < nCurves; i++) {
+        sc = cmsConvertGammaToSampledCurve(Curves[i], 4096);
+        cmsFreeGamma(Curves[i]);
+        Curves[i] = cmsConvertSampledCurveToGamma(sc, 0xFFFF);
+        cmsFreeSampledCurve(sc);
+    }
+
+}
+
+
+static
 void SkipAlignment(LPLCMSICCPROFILE Icc)
 {
     BYTE Buffer[4];
@@ -1121,7 +1226,7 @@
 
 // Read a set of curves from specific offset
 static
-BOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
+LCMSBOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
 {
     LPGAMMATABLE Curves[MAXCHANNELS];
     unsigned int i, nCurves;
@@ -1134,20 +1239,41 @@
     else
         nCurves = NewLUT ->OutputChan;
 
+    ZeroMemory(Curves, sizeof(Curves));
     for (i=0; i < nCurves; i++) {
 
         Curves[i] = ReadCurve(Icc);
+        if (Curves[i] == NULL) goto Error;
         SkipAlignment(Icc);
-
+    }
+
+    // March-26'08: some V4 profiles may have different sampling
+    // rates, in this case resample all curves to maximum
+
+    for (i=1; i < nCurves; i++) {
+        if (Curves[i]->nEntries != Curves[0]->nEntries) {
+            ResampleCurves(Curves, nCurves);
+        break;
+        }
     }
 
     NewLUT = cmsAllocLinearTable(NewLUT, Curves, nLocation);
+    if (NewLUT == NULL) goto Error;
 
     for (i=0; i < nCurves; i++)
         cmsFreeGamma(Curves[i]);
 
     return TRUE;
 
+Error:
+
+    for (i=0; i < nCurves; i++)
+        if (Curves[i])
+            cmsFreeGamma(Curves[i]);
+
+    return FALSE;
+
+
 }
 
 // V4 stuff. LutAtoB type
@@ -1160,22 +1286,28 @@
 //   L2 = B curves
 
 static
-BOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
+LCMSBOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
 {
     icLutAtoB LUT16;
 
-       Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc);
+       if (Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc) != 1) return FALSE;
 
        NewLUT -> InputChan     = LUT16.inputChan;
        NewLUT -> OutputChan    = LUT16.outputChan;
 
+       // Validate the NewLUT here to avoid excessive number of channels
+       // (leading to stack-based buffer overflow in ReadSetOfCurves).
+       // Needs revalidation after table size is filled in.
+       if (!_cmsValidateLUT(NewLUT)) {
+           return FALSE;
+       }
+
        AdjustEndianess32((LPBYTE) &LUT16.offsetB);
        AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
        AdjustEndianess32((LPBYTE) &LUT16.offsetM);
        AdjustEndianess32((LPBYTE) &LUT16.offsetC);
        AdjustEndianess32((LPBYTE) &LUT16.offsetA);
 
-
        if (LUT16.offsetB != 0)
                 ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetB, NewLUT, 2);
 
@@ -1220,15 +1352,22 @@
 // V4 stuff. LutBtoA type
 
 static
-BOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT,  size_t BaseOffset, icTagSignature sig)
+LCMSBOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT,  size_t BaseOffset, icTagSignature sig)
 {
   icLutBtoA LUT16;
 
-       Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc);
+       if (Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc) != 1) return FALSE;
 
        NewLUT -> InputChan     = LUT16.inputChan;
        NewLUT -> OutputChan    = LUT16.outputChan;
 
+       // Validate the NewLUT here to avoid excessive number of channels
+       // (leading to stack-based buffer overflow in ReadSetOfCurves).
+       // Needs revalidation after table size is filled in.
+       if (!_cmsValidateLUT(NewLUT)) {
+           return FALSE;
+       }
+
        AdjustEndianess32((LPBYTE) &LUT16.offsetB);
        AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
        AdjustEndianess32((LPBYTE) &LUT16.offsetM);
@@ -1242,7 +1381,6 @@
        if (LUT16.offsetMat != 0)
             ReadMatrixOffset(Icc, BaseOffset + LUT16.offsetMat, NewLUT, LUT_HASMATRIX3);
 
-
        if (LUT16.offsetM != 0)
                 ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetM, NewLUT, 3);
 
@@ -1294,7 +1432,7 @@
 
 
     // If is in memory, the LUT is already there, so throw a copy
-    if (!Icc -> stream) {
+    if (Icc -> TagPtrs[n]) {
 
         return cmsDupLUT((LPLUT) Icc ->TagPtrs[n]);
     }
@@ -1308,8 +1446,8 @@
 
 
     NewLUT = cmsAllocLUT();
-    if (!NewLUT)
-    {
+    if (!NewLUT) {
+
        cmsSignalError(LCMS_ERRC_ABORTED, "cmsAllocLUT() failed");
        return NULL;
     }
@@ -1317,11 +1455,29 @@
 
     switch (BaseType) {
 
-    case icSigLut8Type:    ReadLUT8(Icc, NewLUT, sig); break;
-    case icSigLut16Type:   ReadLUT16(Icc, NewLUT);     break;
-
-    case icSiglutAtoBType: ReadLUT_A2B(Icc, NewLUT, offset, sig); break;
-    case icSiglutBtoAType: ReadLUT_B2A(Icc, NewLUT, offset, sig); break;
+    case icSigLut8Type:    if (!ReadLUT8(Icc, NewLUT, sig)) {
+                                cmsFreeLUT(NewLUT);
+                                return NULL;
+                           }
+                           break;
+
+    case icSigLut16Type:   if (!ReadLUT16(Icc, NewLUT)) {
+                                cmsFreeLUT(NewLUT);
+                                return NULL;
+                           }
+                           break;
+
+    case icSiglutAtoBType: if (!ReadLUT_A2B(Icc, NewLUT, offset, sig)) {
+                                cmsFreeLUT(NewLUT);
+                                return NULL;
+                           }
+                           break;
+
+    case icSiglutBtoAType: if (!ReadLUT_B2A(Icc, NewLUT, offset, sig)) {
+                                cmsFreeLUT(NewLUT);
+                                return NULL;
+                           }
+                           break;
 
     default:  cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
               cmsFreeLUT(NewLUT);
@@ -1335,16 +1491,23 @@
 
 // Sets the language & country preferences. Used only in ICC 4.0 profiles
 
-void LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode)
+void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4])
 {
-    GlobalLanguageCode = LanguageCode;
-    GlobalCountryCode  = CountryCode;
+
+    int LanguageCodeInt = *(int *) LanguageCode;
+    int CountryCodeInt  = *(int *) CountryCode;
+
+    AdjustEndianess32((LPBYTE) &LanguageCodeInt);
+    AdjustEndianess32((LPBYTE) &CountryCodeInt);
+
+    GlobalLanguageCode = LanguageCodeInt;
+    GlobalCountryCode  = CountryCodeInt;
 }
 
 
 
 // Some tags (e.g, 'pseq') can have text tags embedded. This function
-// handles such special case.
+// handles such special case. Returns -1 on error, or the number of bytes left on success.
 
 static
 int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t size_max)
@@ -1353,7 +1516,6 @@
 
 
     BaseType = ReadBase(Icc);
-
     size -= sizeof(icTagBase);
 
     switch (BaseType) {
@@ -1365,50 +1527,54 @@
            icUInt16Number  ScriptCodeCode, Dummy;
            icUInt8Number   ScriptCodeCount;
 
-           Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc);
-
-                   if (size < sizeof(icUInt32Number)) return (int) size;
+           if (Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
+
+           if (size < sizeof(icUInt32Number)) return (int) size;
            size -= sizeof(icUInt32Number);
 
            AdjustEndianess32((LPBYTE) &AsciiCount);
            Icc ->Read(Name, 1,
                 (AsciiCount >= size_max) ? (size_max-1) : AsciiCount, Icc);
 
-                   if (size < AsciiCount) return (int) size;
+           if (size < AsciiCount) return (int) size;
            size -= AsciiCount;
 
            // Skip Unicode code
 
-           Icc ->Read(&UnicodeCode,  sizeof(icUInt32Number), 1, Icc);
-                   if (size < sizeof(icUInt32Number)) return (int) size;
+           if (Icc ->Read(&UnicodeCode,  sizeof(icUInt32Number), 1, Icc) != 1) return -1;
+           if (size < sizeof(icUInt32Number)) return (int) size;
            size -= sizeof(icUInt32Number);
 
-           Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc);
-                   if (size < sizeof(icUInt32Number)) return (int) size;
+           if (Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
+           if (size < sizeof(icUInt32Number)) return (int) size;
            size -= sizeof(icUInt32Number);
 
            AdjustEndianess32((LPBYTE) &UnicodeCount);
 
            if (UnicodeCount > size) return (int) size;
 
-           for (i=0; i < UnicodeCount; i++)
-                Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc);
-
-           size -= UnicodeCount * sizeof(icUInt16Number);
+           for (i=0; i < UnicodeCount; i++) {
+                size_t nread = Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc);
+                if (nread != 1) return (int) size;
+                size -= sizeof(icUInt16Number);
+           }
 
           // Skip ScriptCode code
 
-           Icc ->Read(&ScriptCodeCode,  sizeof(icUInt16Number), 1, Icc);
+           if (Icc ->Read(&ScriptCodeCode,  sizeof(icUInt16Number), 1, Icc) != 1) return -1;
            size -= sizeof(icUInt16Number);
-           Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc);
+           if (Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc) != 1) return -1;
            size -= sizeof(icUInt8Number);
 
+           // Should remain 67 bytes as filler
+
            if (size < 67) return (int) size;
 
-           for (i=0; i < 67; i++)
-                Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc);
-
-           size -= 67;
+           for (i=0; i < 67; i++) {
+                size_t nread = Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc);
+                if (nread != 1) return (int) size;
+                size --;
+               }
            }
            break;
 
@@ -1425,7 +1591,7 @@
              size = size_max - 1;
          }
 
-         Icc -> Read(Name, 1, size, Icc);
+         if (Icc -> Read(Name, 1, size, Icc) != size) return -1;
 
          for (i=0; i < Missing; i++)
              Icc -> Read(&Dummy, 1, 1, Icc);
@@ -1445,9 +1611,9 @@
         wchar_t*       wchar  = L"";
 
 
-            Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
+            if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
             AdjustEndianess32((LPBYTE) &Count);
-            Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc);
+            if (Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
             AdjustEndianess32((LPBYTE) &RecLen);
 
             if (RecLen != 12) {
@@ -1458,15 +1624,15 @@
 
             for (i=0; i < Count; i++) {
 
-                Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc);
+                if (Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
                 AdjustEndianess16((LPBYTE) &Language);
-                Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc);
+                if (Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
                 AdjustEndianess16((LPBYTE) &Country);
 
-                Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc);
+                if (Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
                 AdjustEndianess32((LPBYTE) &ThisLen);
 
-                Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc);
+                if (Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
                 AdjustEndianess32((LPBYTE) &ThisOffset);
 
                 if (Language == GlobalLanguageCode || Offset == 0) {
@@ -1492,14 +1658,18 @@
             for (i=0; i < Offset; i++) {
 
                     char Discard;
-
-                    Icc ->Read(&Discard, 1, 1, Icc);
+                    if (Icc ->Read(&Discard, 1, 1, Icc) != 1) return -1;
             }
 
-            wchar = (wchar_t*) malloc(Len+2);
+
+            // Bound len
+            if (Len < 0) Len = 0;
+            if (Len > 20*1024) Len = 20 * 1024;
+
+            wchar = (wchar_t*) _cmsMalloc(Len*sizeof(wchar_t)+2);
             if (!wchar) return -1;
 
-            Icc ->Read(wchar, 1, Len, Icc);
+            if (Icc ->Read(wchar, 1, Len, Icc) != Len) return -1;
             AdjustEndianessArray16((LPWORD) wchar, Len / 2);
 
             wchar[Len / 2] = L'\0';
@@ -1509,7 +1679,7 @@
                 Name[0] = 0;    // Error
             }
 
-            free((void*) wchar);
+            _cmsFree((void*) wchar);
             }
             break;
 
@@ -1522,8 +1692,7 @@
 }
 
 
-// Take an ASCII item. Takes at most LCMS_DESC_MAX
-
+// Take an ASCII item. Takes at most size_max bytes
 
 int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Name, size_t size_max)
 {
@@ -1535,19 +1704,27 @@
     if (n < 0)
         return -1;
 
-    if (!Icc -> stream) {
-
-        CopyMemory(Name, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
+     size   = Icc -> TagSizes[n];
+
+    if (Icc -> TagPtrs[n]) {
+
+        if (size > size_max)
+            size = size_max;
+
+        CopyMemory(Name, Icc -> TagPtrs[n], size);
+
         return (int) Icc -> TagSizes[n];
     }
 
     offset = Icc -> TagOffsets[n];
-    size   = Icc -> TagSizes[n];
+
 
     if (Icc -> Seek(Icc, offset))
             return -1;
 
-    return ReadEmbeddedTextTag(Icc, size, Name, size_max);
+    if (ReadEmbeddedTextTag(Icc, size, Name, size_max) < 0) return -1;
+
+        return size;
 }
 
 // Keep compatibility with older versions
@@ -1561,7 +1738,7 @@
 // Take an XYZ item
 
 static
-int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, BOOL lIsFatal)
+int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, LCMSBOOL lIsFatal)
 {
     LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
     icTagTypeSignature  BaseType;
@@ -1573,7 +1750,7 @@
     if (n < 0)
             return -1;
 
-    if (!Icc -> stream) {
+    if (Icc -> TagPtrs[n]) {
 
          CopyMemory(Value, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
          return (int) Icc -> TagSizes[n];
@@ -1628,7 +1805,7 @@
     if (n < 0)
             return -1; // Not found
 
-    if (!Icc -> stream) {
+    if (Icc -> TagPtrs[n]) {
 
             CopyMemory(v, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
             return (int) Icc -> TagSizes[n];
@@ -1677,7 +1854,7 @@
 
 // Primaries are to be in xyY notation
 
-BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
 {
        if (ReadICCXYZ(hProfile, icSigRedColorantTag, &Dest -> Red, TRUE) < 0) return FALSE;
        if (ReadICCXYZ(hProfile, icSigGreenColorantTag, &Dest -> Green, TRUE) < 0) return FALSE;
@@ -1687,7 +1864,7 @@
 }
 
 
-BOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
+LCMSBOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
 {
        cmsCIEXYZTRIPLE Primaries;
 
@@ -1704,7 +1881,7 @@
 
 // Always return a suitable matrix
 
-BOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile)
+LCMSBOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile)
 {
 
     if (ReadICCXYZArray(hProfile, icSigChromaticAdaptationTag, r) < 0) {
@@ -1741,7 +1918,7 @@
        if (n < 0)
            return NULL;
 
-       if (!Icc -> stream) {
+       if (Icc -> TagPtrs[n]) {
 
             return cmsDupGamma((LPGAMMATABLE) Icc -> TagPtrs[n]);
        }
@@ -1769,7 +1946,7 @@
        if (n < 0)
             return NULL;
 
-       if (!Icc -> stream) {
+       if (Icc -> TagPtrs[n]) {
 
             return cmsReverseGamma(256, (LPGAMMATABLE) Icc -> TagPtrs[n]);
        }
@@ -1785,7 +1962,7 @@
 // Check Named color header
 
 static
-BOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2)
+LCMSBOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2)
 {
     if (v ->Prefix[0] == 0 && v ->Suffix[0] == 0 && v ->ColorantCount == 0) return TRUE;
 
@@ -1809,13 +1986,13 @@
        if (n < 0)
             return 0;
 
-       if (!Icc -> stream) {
+       if (Icc -> TagPtrs[n]) {
 
             // This replaces actual named color list.
             size_t size   = Icc -> TagSizes[n];
 
             if (v ->NamedColorList) cmsFreeNamedColorList(v ->NamedColorList);
-            v -> NamedColorList = (LPcmsNAMEDCOLORLIST) malloc(size);
+            v -> NamedColorList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
             CopyMemory(v -> NamedColorList, Icc ->TagPtrs[n], size);
             return v ->NamedColorList->nColors;
        }
@@ -1844,7 +2021,7 @@
                 icNamedColor2 nc2;
                 unsigned int i, j;
 
-                Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc);
+                if (Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return 0;
                 AdjustEndianess32((LPBYTE) &nc2.vendorFlag);
                 AdjustEndianess32((LPBYTE) &nc2.count);
                 AdjustEndianess32((LPBYTE) &nc2.nDeviceCoords);
@@ -1854,6 +2031,11 @@
                      return 0;
                 }
 
+                if (nc2.nDeviceCoords > MAXCHANNELS) {
+                          cmsSignalError(LCMS_ERRC_WARNING, "Too many device coordinates.");
+                          return 0;
+                }
+
                 strncpy(v ->NamedColorList->Prefix, (const char*) nc2.prefix, 32);
                 strncpy(v ->NamedColorList->Suffix, (const char*) nc2.suffix, 32);
                 v ->NamedColorList->Prefix[32] = v->NamedColorList->Suffix[32] = 0;
@@ -1900,7 +2082,8 @@
 
 LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig)
 {
-    icInt32Number n, Count, i;
+    icInt32Number n;
+    icUInt32Number Count, i;
     size_t offset;
     icTagTypeSignature  BaseType;
     LPLCMSICCPROFILE   Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
@@ -1910,10 +2093,12 @@
     if (n < 0)
             return NULL; // Not found
 
-    if (!Icc -> stream) {
+    if (Icc -> TagPtrs[n]) {
 
             size_t size   = Icc -> TagSizes[n];
-            void* v = malloc(size);
+            void* v = _cmsMalloc(size);
+
+            if (v == NULL) return NULL;
             CopyMemory(v, Icc -> TagPtrs[n], size);
             return (LPcmsNAMEDCOLORLIST) v;
     }
@@ -1932,13 +2117,17 @@
     }
 
 
-    Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
+    if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
     AdjustEndianess32((LPBYTE) &Count);
 
+    if (Count > MAXCHANNELS) {
+        cmsSignalError(LCMS_ERRC_ABORTED, "Too many colorants '%lx'", Count);
+        return NULL;
+    }
+
     List = cmsAllocNamedColorList(Count);
     for (i=0; i < Count; i++) {
 
-
         if (!Icc ->Read(List->List[i].Name, 1, 32 , Icc)) goto Error;
         if (!Icc ->Read(List->List[i].PCS, sizeof(icUInt16Number), 3, Icc)) goto Error;
         AdjustEndianessArray16(List->List[i].PCS, 3);
@@ -1965,7 +2154,7 @@
 
        if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
 
-            cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer);
+            cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
        }
 
     return Manufacturer;
@@ -1982,7 +2171,7 @@
 
        if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
 
-            cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model);
+            cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
        }
 
     return Model;
@@ -1995,10 +2184,9 @@
     static char Copyright[LCMS_DESC_MAX] = "";
 
        Copyright[0] = 0;
-
        if (cmsIsTag(hProfile, icSigCopyrightTag)) {
 
-            cmsReadICCText(hProfile, icSigCopyrightTag, Copyright);
+            cmsReadICCTextEx(hProfile, icSigCopyrightTag, Copyright, LCMS_DESC_MAX);
        }
 
     return Copyright;
@@ -2009,7 +2197,7 @@
 
 const char*  LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile)
 {
-    static char Name[2048];
+    static char Name[LCMS_DESC_MAX*2+4];
     char Manufacturer[LCMS_DESC_MAX], Model[LCMS_DESC_MAX];
 
     Name[0] = '\0';
@@ -2017,19 +2205,19 @@
 
     if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
 
-        cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer);
+        cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
     }
 
     if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
 
-        cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model);
+        cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
     }
 
     if (!Manufacturer[0] && !Model[0]) {
 
         if (cmsIsTag(hProfile, icSigProfileDescriptionTag)) {
 
-            cmsReadICCText(hProfile, icSigProfileDescriptionTag, Name);
+            cmsReadICCTextEx(hProfile, icSigProfileDescriptionTag, Name, LCMS_DESC_MAX);
             return Name;
         }
         else return "{no name}";
@@ -2129,7 +2317,7 @@
 
 // Extract the target data as a big string. Does not signal if tag is not present.
 
-BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len)
+LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len)
 {
     LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
     int n;
@@ -2142,7 +2330,11 @@
 
 
     *len =  Icc -> TagSizes[n];
-    *Data = (char*) malloc(*len + 1);  // Plus zero marker
+
+    // Make sure that is reasonable (600K)
+    if (*len > 600*1024) *len = 600*1024;
+
+    *Data = (char*) _cmsMalloc(*len + 1);  // Plus zero marker
 
     if (!*Data) {
 
@@ -2162,7 +2354,7 @@
 
 
 
-BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
 {
     LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
     int n;
@@ -2170,8 +2362,8 @@
     n = _cmsSearchTag(Icc, icSigCalibrationDateTimeTag, FALSE);
     if (n < 0) return FALSE;
 
-    if (!Icc ->stream)
-    {
+    if (Icc ->TagPtrs[n]) {
+
         CopyMemory(Dest, Icc ->TagPtrs[n],  sizeof(struct tm));
     }
     else
@@ -2212,9 +2404,10 @@
     size   = Icc -> TagSizes[n];
     if (size < 12)  return NULL;
 
-    if (!Icc -> stream) {
-
-            OutSeq = (LPcmsSEQ) malloc(size);
+    if (Icc -> TagPtrs[n]) {
+
+            OutSeq = (LPcmsSEQ) _cmsMalloc(size);
+            if (OutSeq == NULL) return NULL;
             CopyMemory(OutSeq, Icc ->TagPtrs[n], size);
             return OutSeq;
     }
@@ -2231,8 +2424,13 @@
     Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
     AdjustEndianess32((LPBYTE) &Count);
 
+    if (Count > 1000) {
+         return NULL;
+    }
+
     size = sizeof(int) + Count * sizeof(cmsPSEQDESC);
-    OutSeq = (LPcmsSEQ) malloc(size);
+    OutSeq = (LPcmsSEQ) _cmsMalloc(size);
+    if (OutSeq == NULL) return NULL;
 
     OutSeq ->n = Count;
 
@@ -2268,181 +2466,11 @@
 void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq)
 {
     if (pseq)
-        free(pseq);
+        _cmsFree(pseq);
 }
 
 
 
-// Extended gamut -- an HP extension
-
-
-LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index)
-{
-    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
-    size_t size, offset;
-    icUInt32Number off_samp, off_desc, off_vc;
-    int n;
-    icTagTypeSignature     BaseType;
-    icColorSpaceSignature  CoordSig;
-    icUInt16Number         Method, Usage;
-    icUInt32Number         GamutCount, SamplesCount;
-    LPcmsGAMUTEX gex;
-    size_t                 Offsets[256];
-    size_t                 i, Actual, Loc;
-    icS15Fixed16Number     Num;
-    icUInt16Number         Surround;
-
-
-    n = _cmsSearchTag(Icc, icSigHPGamutDescTag, FALSE);
-    if (n < 0) return NULL;
-
-    if (!Icc ->stream) return NULL;     // In memory is not supported
-
-    // Read the header
-
-    offset = Icc -> TagOffsets[n];
-
-    if (Icc -> Seek(Icc, offset))
-            return NULL;
-
-    // Here is the beginning of tag
-    Actual   = Icc ->Tell(Icc);
-
-
-    BaseType = ReadBase(Icc);
-
-    if (BaseType != icSigHPGamutDescType) {
-            cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType);
-            return NULL;
-    }
-
-
-    // Read the gamut descriptors count
-    Icc ->Read(&GamutCount, sizeof(icUInt32Number), 1, Icc);
-    AdjustEndianess32((LPBYTE) &GamutCount);
-
-
-    if (GamutCount >= 256) {
-            cmsSignalError(LCMS_ERRC_ABORTED, "Too many gamut structures '%d'.", GamutCount);
-            return NULL;
-    }
-
-    // Read the directory
-
-    for (i=0; i < GamutCount; i++) {
-
-        Icc ->Read(&Offsets[i], sizeof(icUInt32Number), 1, Icc);
-        AdjustEndianess32((LPBYTE) &Offsets[i]);
-    }
-
-
-    // Is there such element?
-    if (index >= (int) GamutCount) return NULL;
-    Loc = Actual + Offsets[index];
-
-
-    // Go to specified index
-    if (Icc -> Seek(Icc, Loc))
-            return NULL;
-
-
-    // Read all members
-    Icc ->Read(&CoordSig, sizeof(icColorSpaceSignature), 1, Icc);
-    AdjustEndianess32((LPBYTE) &CoordSig);
-
-    Icc ->Read(&Method, sizeof(icUInt16Number), 1, Icc);
-    AdjustEndianess16((LPBYTE) &Method);
-
-    Icc ->Read(&Usage, sizeof(icUInt16Number), 1, Icc);
-    AdjustEndianess16((LPBYTE) &Usage);
-
-    Icc ->Read(&SamplesCount, sizeof(icUInt32Number), 1, Icc);
-    AdjustEndianess32((LPBYTE) &SamplesCount);
-
-    Icc ->Read(&off_samp, sizeof(icUInt32Number), 1, Icc);
-    AdjustEndianess32((LPBYTE) &off_samp);
-
-    Icc ->Read(&off_desc, sizeof(icUInt32Number), 1, Icc);
-    AdjustEndianess32((LPBYTE) &off_desc);
-
-    Icc ->Read(&off_vc, sizeof(icUInt32Number), 1, Icc);
-    AdjustEndianess32((LPBYTE) &off_vc);
-
-
-    size = sizeof(cmsGAMUTEX) + (SamplesCount - 1) * sizeof(double);
-
-    gex = (LPcmsGAMUTEX) malloc(size);
-        if (gex == NULL) return NULL;
-
-
-    gex ->CoordSig = CoordSig;
-    gex ->Method   = Method;
-    gex ->Usage    = Usage;
-        gex ->Count    = SamplesCount;
-
-
-    // Read data
-    if (Icc -> Seek(Icc, Loc + off_samp))
-            return NULL;
-
-    for (i=0; i < SamplesCount; i++) {
-                Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-                gex ->Data[i] = Convert15Fixed16(Num);
-    }
-
-
-    // Read mluc
-    if (Icc -> Seek(Icc, Loc + off_desc)) {
-
-                        free(gex);
-            return NULL;
-        }
-
-    ReadEmbeddedTextTag(Icc, 256, gex ->Description, LCMS_DESC_MAX);
-
-
-    // Read viewing conditions
-    if (Icc -> Seek(Icc, Loc + off_vc)) {
-                        free(gex);
-            return NULL;
-        }
-
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.whitePoint.X = Convert15Fixed16(Num);
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.whitePoint.Y = Convert15Fixed16(Num);
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.whitePoint.Z = Convert15Fixed16(Num);
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.La = Convert15Fixed16(Num);
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.Yb = Convert15Fixed16(Num);
-
-    Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
-    gex ->Vc.D_value = Convert15Fixed16(Num);
-
-    Icc -> Read(&Surround, sizeof(icUInt16Number), 1, Icc);
-    AdjustEndianess16((LPBYTE) &Surround);
-    gex ->Vc.surround = Surround;
-
-
-    // All OK
-    return gex;
-
-}
-
-
-
-void LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex)
-{
-    if (gex)
-        free(gex);
-}
 
 
 // Read a few tags that are hardly required
@@ -2564,6 +2592,7 @@
            NewIcc = (LPLCMSICCPROFILE) (LPSTR) hEmpty;
            NewIcc -> IsWrite = TRUE;
            strncpy(NewIcc ->PhysicalFile, lpFileName, MAX_PATH-1);
+           NewIcc ->PhysicalFile[MAX_PATH-1] = 0;
 
            // Save LUT as 8 bit
 
@@ -2609,14 +2638,14 @@
 
 
 
-BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
 {
        LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
-       BOOL rc = TRUE;
+       LCMSBOOL rc = TRUE;
+       icInt32Number i;
 
        if (!Icc) return FALSE;
 
-
        // Was open in write mode?
        if (Icc ->IsWrite) {
 
@@ -2624,21 +2653,15 @@
            rc = _cmsSaveProfile(hProfile, Icc ->PhysicalFile);
        }
 
-
-       if (Icc -> stream == NULL) {     // Was a memory (i.e. not serialized) profile?
-
-
-              icInt32Number i;          // Yes, free tags
-
-              for (i=0; i < Icc -> TagCount; i++) {
+       for (i=0; i < Icc -> TagCount; i++) {
 
                   if (Icc -> TagPtrs[i])
                             free(Icc -> TagPtrs[i]);
-              }
-
        }
-       else   Icc -> Close(Icc);    // No, close the stream
-
+
+       if (Icc -> stream != NULL) {     // Was a memory (i.e. not serialized) profile?
+                 Icc -> Close(Icc);     // No, close the stream
+       }
 
        free(Icc);   // Free placeholder memory
 
@@ -2652,11 +2675,11 @@
 
 
 static
-BOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
 {
    size_t nTabSize = sizeof(WORD) * nEntries;
-   LPWORD PtrW = (LPWORD) malloc(nTabSize);
-   BOOL rc;
+   LPWORD PtrW = (LPWORD) _cmsMalloc(nTabSize);
+   LCMSBOOL rc;
 
    if (!PtrW) return FALSE;
    CopyMemory(PtrW, Tab, nTabSize);
@@ -2672,7 +2695,7 @@
 // Saves profile header
 
 static
-BOOL SaveHeader(LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveHeader(LPLCMSICCPROFILE Icc)
 {
   icHeader Header;
   time_t now = time(NULL);
@@ -2727,7 +2750,7 @@
 // Setup base marker
 
 static
-BOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
+LCMSBOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
 {
     icTagBase  Base;
 
@@ -2737,10 +2760,10 @@
 }
 
 
-// Store an XYZ tag
+// Store a XYZ tag
 
 static
-BOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
 {
 
     icXYZNumber XYZ;
@@ -2756,72 +2779,97 @@
 }
 
 
+// Store a XYZ array.
+
+static
+LCMSBOOL SaveXYZArray(int n, LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
+{
+    int i;
+    icXYZNumber XYZ;
+
+    if (!SetupBase(icSigS15Fixed16ArrayType, Icc)) return FALSE;
+
+    for (i=0; i < n; i++) {
+
+        XYZ.X = TransportValue32(DOUBLE_TO_FIXED(Value -> X));
+        XYZ.Y = TransportValue32(DOUBLE_TO_FIXED(Value -> Y));
+        XYZ.Z = TransportValue32(DOUBLE_TO_FIXED(Value -> Z));
+
+        if (!Icc -> Write(Icc, sizeof(icXYZNumber), &XYZ)) return FALSE;
+
+        Value++;
+    }
+
+    return TRUE;
+}
+
+
 
 // Save a gamma structure as a table
 
 static
-BOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
 {
-        icInt32Number Count;
-
-                if (!SetupBase(icSigCurveType, Icc)) return FALSE;
-
-                Count = TransportValue32(Gamma->nEntries);
-
-                if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
-
-                return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc);
+    icInt32Number Count;
+
+        if (!SetupBase(icSigCurveType, Icc)) return FALSE;
+
+        Count = TransportValue32(Gamma->nEntries);
+
+        if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
+
+        return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc);
 }
 
 
 // Save a gamma structure as a one-value
 
 static
-BOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
 {
-        icInt32Number Count;
-        Fixed32 GammaFixed32;
-        WORD    GammaFixed8;
-
-                if (!SetupBase(icSigCurveType, Icc)) return FALSE;
-
-                Count = TransportValue32(1);
-                if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
-
-                GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]);
-                GammaFixed8  = (WORD) ((GammaFixed32 >> 8) & 0xFFFF);
-                GammaFixed8  = TransportValue16(GammaFixed8);
-
-                return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8);
+    icInt32Number Count;
+    Fixed32 GammaFixed32;
+    WORD    GammaFixed8;
+
+        if (!SetupBase(icSigCurveType, Icc)) return FALSE;
+
+        Count = TransportValue32(1);
+        if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
+
+        GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]);
+        GammaFixed8  = (WORD) ((GammaFixed32 >> 8) & 0xFFFF);
+        GammaFixed8  = TransportValue16(GammaFixed8);
+
+        return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8);
 }
 
 // Save a gamma structure as a parametric gamma
 
 static
-BOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
 {
-        icUInt16Number Type, Reserved;
-        int i, nParams;
-        int ParamsByType[] = { 1, 3, 4, 5, 7 };
-
-        if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE;
-
-        nParams = ParamsByType[Gamma -> Seed.Type];
-
-        Type      = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type);
-        Reserved  = (icUInt16Number) TransportValue16((WORD) 0);
-
-        Icc -> Write(Icc, sizeof(icInt16Number),  &Type);
-        Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved);
-
-        for (i=0; i < nParams; i++) {
-
-                icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i]));
-                Icc ->Write(Icc, sizeof(icInt32Number), &val);
-        }
-
-
-        return TRUE;
+    icUInt16Number Type, Reserved;
+    int i, nParams;
+    int ParamsByType[] = { 1, 3, 4, 5, 7 };
+
+    if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE;
+
+    nParams = ParamsByType[Gamma -> Seed.Type];
+
+    Type      = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type);
+    Reserved  = (icUInt16Number) TransportValue16((WORD) 0);
+
+    Icc -> Write(Icc, sizeof(icInt16Number),  &Type);
+    Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved);
+
+    for (i=0; i < nParams; i++) {
+
+        icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i]));
+        Icc ->Write(Icc, sizeof(icInt32Number), &val);
+    }
+
+
+    return TRUE;
 
 }
 
@@ -2829,29 +2877,29 @@
 // Save a gamma table
 
 static
-BOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
 {
-                // Is the gamma curve type supported by ICC format?
-
-                if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 ||
-
-                        // has been modified by user?
-
-                        _cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) {
-
-                        return SaveGammaTable(Gamma, Icc);
-                }
-
-                if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc);
-
-                // Only v4 profiles are allowed to hold parametric curves
-
-                if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000)
-                                return SaveGammaParametric(Gamma, Icc);
-
-                // Defaults to save as table
-
-                return SaveGammaTable(Gamma, Icc);
+        // Is the gamma curve type supported by ICC format?
+
+        if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 ||
+
+            // has been modified by user?
+
+            _cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) {
+
+            return SaveGammaTable(Gamma, Icc);
+        }
+
+        if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc);
+
+        // Only v4 profiles are allowed to hold parametric curves
+
+        if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000)
+                return SaveGammaParametric(Gamma, Icc);
+
+        // Defaults to save as table
+
+        return SaveGammaTable(Gamma, Icc);
 
 }
 
@@ -2861,7 +2909,7 @@
 // Save an DESC Tag
 
 static
-BOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
 {
 
     icUInt32Number len, Count, TotalSize, AlignedSize;
@@ -2893,6 +2941,11 @@
     if (!Icc ->Write(Icc, len, (LPVOID)Text)) return FALSE;
     AlignedSize -= len;
 
+    if (AlignedSize < 0)
+            AlignedSize = 0;
+    if (AlignedSize > 255)
+            AlignedSize = 255;
+
     ZeroMemory(Filler, AlignedSize);
     if (!Icc ->Write(Icc, AlignedSize, Filler)) return FALSE;
 
@@ -2902,7 +2955,7 @@
 // Save an ASCII Tag
 
 static
-BOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
 {
     size_t len = strlen(Text) + 1;
 
@@ -2915,7 +2968,7 @@
 // Save one of these new chromaticity values
 
 static
-BOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
 {
        Fixed32 xf, yf;
 
@@ -2932,7 +2985,7 @@
 // New tag added in Addendum II of old spec.
 
 static
-BOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
 {
        WORD nChans, Table;
 
@@ -2952,7 +3005,7 @@
 
 
 static
-BOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
 {
     icUInt32Number nSeqs;
     icDescStruct   DescStruct;
@@ -2989,7 +3042,7 @@
 // Saves a timestamp tag
 
 static
-BOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
 {
     icDateTimeNumber Dest;
 
@@ -3003,14 +3056,14 @@
 
 // Saves a named color list into a named color profile
 static
-BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
 {
 
     icUInt32Number      vendorFlag;     // Bottom 16 bits for IC use
     icUInt32Number      count;          // Count of named colors
     icUInt32Number      nDeviceCoords;  // Num of device coordinates
-    icInt8Number        prefix[32];     // Prefix for each color name
-    icInt8Number        suffix[32];     // Suffix for each color name
+    char                prefix[32];     // Prefix for each color name
+    char                suffix[32];     // Suffix for each color name
     int i;
 
     if (!SetupBase(icSigNamedColor2Type, Icc)) return FALSE;
@@ -3019,8 +3072,10 @@
     count         = TransportValue32(NamedColorList ->nColors);
     nDeviceCoords = TransportValue32(NamedColorList ->ColorantCount);
 
-    strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
-    strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
+    strncpy(prefix, (const char*) NamedColorList->Prefix, 31);
+    strncpy(suffix, (const char*) NamedColorList->Suffix, 31);
+
+    suffix[31] = prefix[31] = 0;
 
     if (!Icc ->Write(Icc, sizeof(icUInt32Number), &vendorFlag)) return FALSE;
     if (!Icc ->Write(Icc, sizeof(icUInt32Number), &count)) return FALSE;
@@ -3030,15 +3085,17 @@
 
     for (i=0; i < NamedColorList ->nColors; i++) {
 
-          icUInt16Number PCS[3];
-          icUInt16Number Colorant[MAXCHANNELS];
-          icInt8Number root[32];
+          icUInt16Number  PCS[3];
+          icUInt16Number  Colorant[MAXCHANNELS];
+          char            root[32];
           LPcmsNAMEDCOLOR Color;
           int j;
 
                     Color = NamedColorList ->List + i;
 
-                    strncpy((char*) root, Color ->Name, 32);
+                    strncpy(root, Color ->Name, 32);
+                    Color ->Name[32] = 0;
+
                     if (!Icc ->Write(Icc, 32 , root)) return FALSE;
 
                     for (j=0; j < 3; j++)
@@ -3062,7 +3119,7 @@
 // Saves a colorant table. It is using the named color structure for simplicity sake
 
 static
-BOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
 {
      icUInt32Number count;  // Count of named colors
      int i;
@@ -3076,13 +3133,15 @@
      for (i=0; i < NamedColorList ->nColors; i++) {
 
       icUInt16Number PCS[3];
-      icInt8Number root[32];
+      icInt8Number root[33];
       LPcmsNAMEDCOLOR Color;
       int j;
 
             Color = NamedColorList ->List + i;
 
             strncpy((char*) root, Color ->Name, 32);
+            root[32] = 0;
+
             if (!Icc ->Write(Icc, 32 , root)) return FALSE;
 
             for (j=0; j < 3; j++)
@@ -3099,7 +3158,7 @@
 // Does serialization of LUT16 and writes it.
 
 static
-BOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
 {
        icLut16 LUT16;
        unsigned int i;
@@ -3189,7 +3248,7 @@
 // Does serialization of LUT8 and writes it
 
 static
-BOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
 {
        icLut8 LUT8;
        unsigned int i, j;
@@ -3323,7 +3382,7 @@
 // Saves Tag directory
 
 static
-BOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
 {
        icInt32Number i;
        icTag Tag;
@@ -3356,7 +3415,7 @@
 // Dump tag contents
 
 static
-BOOL SaveTags(LPLCMSICCPROFILE Icc)
+LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc, LPLCMSICCPROFILE FileOrig)
 {
 
     LPBYTE Data;
@@ -3384,8 +3443,31 @@
 
        Icc -> TagOffsets[i] = Begin = Icc ->UsedSpace;
        Data = (LPBYTE) Icc -> TagPtrs[i];
-       if (!Data)
+       if (!Data) {
+
+           // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user.
+           // In this case a blind copy of the block data is performed
+
+           if (Icc -> TagOffsets[i]) {
+
+                    size_t TagSize   = FileOrig -> TagSizes[i];
+                    size_t TagOffset = FileOrig -> TagOffsets[i];
+                    void* Mem;
+
+                    if (FileOrig ->Seek(FileOrig, TagOffset)) return FALSE;
+
+                    Mem = _cmsMalloc(TagSize);
+
+                    if (FileOrig ->Read(Mem, TagSize, 1, FileOrig) != 1) return FALSE;
+                    if (!Icc ->Write(Icc, TagSize, Mem)) return FALSE;
+
+                    Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin);
+                    free(Mem);
+           }
+
               continue;
+       }
+
 
        switch (Icc -> TagNames[i]) {
 
@@ -3464,6 +3546,10 @@
              break;
 
 
+       case icSigChromaticAdaptationTag:
+              if (!SaveXYZArray(3, (LPcmsCIEXYZ) Data, Icc)) return FALSE;
+              break;
+
        default:
               return FALSE;
        }
@@ -3480,9 +3566,9 @@
 
 // Add tags to profile structure
 
-BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag)
+LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag)
 {
-   BOOL rc;
+   LCMSBOOL rc;
 
    switch (sig) {
 
@@ -3543,6 +3629,11 @@
               rc = _cmsAddColorantTableTag(hProfile, sig, (LPcmsNAMEDCOLORLIST) Tag);
               break;
 
+
+       case icSigChromaticAdaptationTag:
+              rc = _cmsAddChromaticAdaptationTag(hProfile, sig, (const cmsCIEXYZ*) Tag);
+              break;
+
        default:
             cmsSignalError(LCMS_ERRC_ABORTED, "cmsAddTag: Tag '%x' is unsupported", sig);
             return FALSE;
@@ -3568,11 +3659,11 @@
 
 // Low-level save to disk. It closes the profile on exit
 
-BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
+LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
 {
        LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
        LCMSICCPROFILE Keep;
-       BOOL rc;
+       LCMSBOOL rc;
 
         CopyMemory(&Keep, Icc, sizeof(LCMSICCPROFILE));
        _cmsSetSaveToDisk(Icc, NULL);
@@ -3581,7 +3672,7 @@
 
        if (!SaveHeader(Icc)) return FALSE;
        if (!SaveTagDirectory(Icc)) return FALSE;
-       if (!SaveTags(Icc)) return FALSE;
+       if (!SaveTags(Icc, &Keep)) return FALSE;
 
 
        _cmsSetSaveToDisk(Icc, FileName);
@@ -3591,7 +3682,7 @@
 
        if (!SaveHeader(Icc)) goto CleanUp;
        if (!SaveTagDirectory(Icc)) goto CleanUp;
-       if (!SaveTags(Icc)) goto CleanUp;
+       if (!SaveTags(Icc, &Keep)) goto CleanUp;
 
        rc = (Icc ->Close(Icc) == 0);
        CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
@@ -3608,7 +3699,7 @@
 
 
 // Low-level save from open stream
-BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
+LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
                                                            size_t* BytesNeeded)
 {
     LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
@@ -3623,20 +3714,20 @@
 
     if (!SaveHeader(Icc)) return FALSE;
     if (!SaveTagDirectory(Icc)) return FALSE;
-    if (!SaveTags(Icc)) return FALSE;
+    if (!SaveTags(Icc, &Keep)) return FALSE;
 
     if (!MemPtr) {
 
         // update BytesSaved so caller knows how many bytes are needed for MemPtr
         *BytesNeeded = Icc ->UsedSpace;
-                CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
+        CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
         return TRUE;
     }
 
     if (*BytesNeeded < Icc ->UsedSpace) {
 
         // need at least UsedSpace in MemPtr to continue
-                CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
+        CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
         return FALSE;
     }
 
@@ -3646,7 +3737,7 @@
     // Pass #2 does save to file into supplied stream
     if (!SaveHeader(Icc)) goto CleanUp;
     if (!SaveTagDirectory(Icc)) goto CleanUp;
-    if (!SaveTags(Icc)) goto CleanUp;
+    if (!SaveTags(Icc, &Keep)) goto CleanUp;
 
     // update BytesSaved so caller knows how many bytes put into stream
     *BytesNeeded = Icc ->UsedSpace;
@@ -3661,3 +3752,4 @@
     CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
     return FALSE;
 }
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -118,7 +118,7 @@
 {
        LPLUT NewLUT;
 
-       NewLUT = (LPLUT) malloc(sizeof(LUT));
+       NewLUT = (LPLUT) _cmsMalloc(sizeof(LUT));
        if (NewLUT)
               ZeroMemory(NewLUT, sizeof(LUT));
 
@@ -171,9 +171,10 @@
 static
 LPVOID DupBlockTab(LPVOID Org, size_t size)
 {
-    LPVOID mem = malloc(size);
+    LPVOID mem = _cmsMalloc(size);
+    if (mem != NULL)
+        CopyMemory(mem, Org, size);
 
-    CopyMemory(mem, Org, size);
     return mem;
 }
 
@@ -211,6 +212,37 @@
 }
 
 
+LCMSBOOL _cmsValidateLUT(LPLUT NewLUT)
+{
+    unsigned int calc = 1;
+    unsigned int oldCalc;
+    unsigned int power = NewLUT -> InputChan;
+
+    if (NewLUT -> cLutPoints > 100) return FALSE;
+    if (NewLUT -> InputChan > MAXCHANNELS)  return FALSE;
+    if (NewLUT -> OutputChan > MAXCHANNELS) return FALSE;
+
+    if (NewLUT -> cLutPoints == 0) return TRUE;
+
+    for (; power > 0; power--) {
+
+      oldCalc = calc;
+      calc *= NewLUT -> cLutPoints;
+
+      if (calc / NewLUT -> cLutPoints != oldCalc) {
+        return FALSE;
+      }
+    }
+
+    oldCalc = calc;
+    calc *= NewLUT -> OutputChan;
+    if (NewLUT -> OutputChan && calc / NewLUT -> OutputChan != oldCalc) {
+      return FALSE;
+    }
+
+    return TRUE;
+}
+
 LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan)
 {
     DWORD nTabSize;
@@ -220,12 +252,17 @@
        NewLUT -> InputChan     = inputChan;
        NewLUT -> OutputChan    = outputChan;
 
+       if (!_cmsValidateLUT(NewLUT)) {
+         return NULL;
+       }
 
-       nTabSize = (NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
-                                                NewLUT->InputChan)
-                                                * sizeof(WORD));
+       nTabSize = NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
+                                               NewLUT->InputChan);
 
-       NewLUT -> T = (LPWORD) malloc(nTabSize);
+       NewLUT -> T = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
+       nTabSize *= sizeof(WORD);
+       if (NewLUT -> T == NULL) return NULL;
+
        ZeroMemory(NewLUT -> T, nTabSize);
        NewLUT ->Tsize = nTabSize;
 
@@ -254,10 +291,12 @@
 
                for (i=0; i < NewLUT -> InputChan; i++) {
 
-                     PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries);
+                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
+                     if (PtrW == NULL) return NULL;
+
                      NewLUT -> L1[i] = PtrW;
                      CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries);
-                                         CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
+                     CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
                }
 
 
@@ -268,10 +307,12 @@
                NewLUT -> OutputEntries = Tables[0] -> nEntries;
                for (i=0; i < NewLUT -> OutputChan; i++) {
 
-                     PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries);
+                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
+                     if (PtrW == NULL) return NULL;
+
                      NewLUT -> L2[i] = PtrW;
                      CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries);
-                                         CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
+                     CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
                }
                break;
 
@@ -285,10 +326,12 @@
 
                for (i=0; i < NewLUT -> InputChan; i++) {
 
-                     PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L3Entries);
+                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L3Entries);
+                     if (PtrW == NULL) return NULL;
+
                      NewLUT -> L3[i] = PtrW;
                      CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries);
-                                         CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
+                     CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
                }
                break;
 
@@ -298,10 +341,12 @@
                NewLUT -> L4Entries = Tables[0] -> nEntries;
                for (i=0; i < NewLUT -> OutputChan; i++) {
 
-                     PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L4Entries);
+                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L4Entries);
+                     if (PtrW == NULL) return NULL;
+
                      NewLUT -> L4[i] = PtrW;
                      CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries);
-                                         CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
+                     CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
                }
                break;
 
@@ -580,7 +625,7 @@
    LPL16PARAMS p = &Lut ->CLut16params;
 
 
-   p8 = (LPL8PARAMS) malloc(sizeof(L8PARAMS));
+   p8 = (LPL8PARAMS) _cmsMalloc(sizeof(L8PARAMS));
    if (p8 == NULL) return NULL;
 
   // values comes * 257, so we can safely take first byte (x << 8 + x)
@@ -593,8 +638,8 @@
            if (Lut ->wFlags & LUT_HASTL1) {
 
               for (j=0; j < 3; j++)
-                     StageABC[i] = cmsLinearInterpLUT16(StageABC[i],
-                                                        Lut -> L1[i],
+                     StageABC[j] = cmsLinearInterpLUT16(StageABC[j],
+                                                        Lut -> L1[j],
                                                        &Lut -> In16params);
               Lut ->wFlags &= ~LUT_HASTL1;
            }
@@ -697,7 +742,7 @@
     wIn[3] = FixedK;
 
     cmsEvalLUT(Lut, wIn, wOut);
-        cmsLabEncoded2Float(Out, wOut);
+    cmsLabEncoded2Float(Out, wOut);
 }
 
 // Builds a Jacobian CMY->Lab
@@ -722,9 +767,9 @@
 
         EvalLUTdoubleKLab(Lut, &ColorantD, K, &LabD);
 
-                Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON);
-                Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON);
-                Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON);
+        Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON);
+        Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON);
+        Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON);
 
     }
 }
@@ -797,18 +842,18 @@
         // Obtain slope
         ComputeJacobianLab(Lut, &Jacobian, &x, FixedK);
 
-                // Solve system
-                tmp2.n[0] = fx.L - Goal.L;
-                tmp2.n[1] = fx.a - Goal.a;
-                tmp2.n[2] = fx.b - Goal.b;
+        // Solve system
+        tmp2.n[0] = fx.L - Goal.L;
+        tmp2.n[1] = fx.a - Goal.a;
+        tmp2.n[2] = fx.b - Goal.b;
 
-                if (!MAT3solve(&tmp, &Jacobian, &tmp2))
-                        break;
+        if (!MAT3solve(&tmp, &Jacobian, &tmp2))
+            break;
 
         // Move our guess
-                x.n[0] -= tmp.n[0];
-            x.n[1] -= tmp.n[1];
-                x.n[2] -= tmp.n[2];
+        x.n[0] -= tmp.n[0];
+        x.n[1] -= tmp.n[1];
+        x.n[2] -= tmp.n[2];
 
         // Some clipping....
         VEC3saturate(&x);
@@ -822,3 +867,6 @@
     return LastError;
 
 }
+
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -62,6 +62,7 @@
 // data yet in fixed point, so no additional process is required.
 // Then, we obtain data on 15.16, so we need to shift >> by 1 to
 // obtain 1.15 PCS format.
+
 // On OUTPUT profiles, things are inverse, we must first expand 1 bit
 // by shifting left, and then convert result between 0 and 1.000 to
 // RGB, so FromFixedDomain() must be called before pass values to
@@ -71,6 +72,7 @@
 // input is encoded from 0 to 0xffff, we must first use the shaper and
 // then the matrix, an additional FromFixedDomain() must be used to
 // accomodate output values.
+
 // For a sake of simplicity, I will handle this three behaviours
 // with different routines, so the flags MATSHAPER_INPUT and MATSHAPER_OUTPUT
 // can be conbined to signal smelted matrix-shapers
@@ -89,7 +91,7 @@
        {
         LPWORD PtrW;
 
-        PtrW = (LPWORD) malloc(sizeof(WORD) * p16 -> nSamples);
+        PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * p16 -> nSamples);
 
         if (PtrW == NULL) return -1;  // Signal error
 
@@ -119,7 +121,7 @@
        LPMATSHAPER NewMatShaper;
        int rc;
 
-       NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER));
+       NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
        if (NewMatShaper)
               ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
 
@@ -171,7 +173,13 @@
        LPMATSHAPER NewMatShaper;
        int i, AllLinear;
 
-       NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER));
+           if (Matrix == NULL) return NULL;
+           for (i=0; i < 3; i++) {
+
+                   if (Tables[i] == NULL) return NULL;
+           }
+
+       NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
        if (NewMatShaper)
               ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
 
@@ -187,17 +195,16 @@
                      NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX;
 
        // Now, on the table characteristics
-
        cmsCalcL16Params(Tables[0] -> nEntries, &NewMatShaper -> p16);
 
        // Copy tables
 
        AllLinear = 0;
-       for (i=0; i < 3; i++)
-       {
+       for (i=0; i < 3; i++) {
+
         LPWORD PtrW;
 
-        PtrW = (LPWORD) malloc(sizeof(WORD) * NewMatShaper -> p16.nSamples);
+        PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewMatShaper -> p16.nSamples);
 
         if (PtrW == NULL) {
               cmsFreeMatShaper(NewMatShaper);
@@ -235,11 +242,11 @@
 
        for (i=0; i < 3; i++)
        {
-              if (MatShaper -> L[i]) free(MatShaper ->L[i]);
-              if (MatShaper -> L2[i]) free(MatShaper ->L2[i]);
+              if (MatShaper -> L[i]) _cmsFree(MatShaper ->L[i]);
+              if (MatShaper -> L2[i]) _cmsFree(MatShaper ->L2[i]);
        }
 
-       free(MatShaper);
+       _cmsFree(MatShaper);
 }
 
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -71,16 +71,16 @@
 double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
 
 
-void   cdecl MAT3identity(LPMAT3 a);
-void   cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
-int    cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
-BOOL   cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
-double cdecl MAT3det(LPMAT3 m);
-void   cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
-void   cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
-void   cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
-void   cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
-void   cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
+void      cdecl MAT3identity(LPMAT3 a);
+void      cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
+int       cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
+LCMSBOOL  cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
+double    cdecl MAT3det(LPMAT3 m);
+void      cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
+void      cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
+void      cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
+void      cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
+void      cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
 
 // --------------------- Implementation ----------------------------
 
@@ -345,13 +345,13 @@
 // Check id two vectors are the same, allowing tolerance
 
 static
-BOOL RangeCheck(double l, double h, double v)
+LCMSBOOL RangeCheck(double l, double h, double v)
 {
        return (v >= l && v <= h);
 }
 
 
-BOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
+LCMSBOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
 {
        int i;
        double c;
@@ -367,7 +367,7 @@
        return TRUE;
 }
 
-BOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance)
+LCMSBOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance)
 {
        int i;
        double c;
@@ -462,7 +462,7 @@
 
 // Check if matrix is Identity. Allow a tolerance as %
 
-BOOL MAT3isIdentity(LPWMAT3 a, double Tolerance)
+LCMSBOOL MAT3isIdentity(LPWMAT3 a, double Tolerance)
 {
        int i;
        MAT3 Idd;
@@ -545,16 +545,16 @@
 
 // Solve a system in the form Ax = b
 
-BOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b)
+LCMSBOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b)
 {
-        MAT3 m, a_1;
+    MAT3 m, a_1;
 
-        CopyMemory(&m, a, sizeof(MAT3));
+    CopyMemory(&m, a, sizeof(MAT3));
 
-        if (!MAT3inverse(&m, &a_1)) return FALSE;  // Singular matrix
+    if (!MAT3inverse(&m, &a_1)) return FALSE;  // Singular matrix
 
-        MAT3eval(x, &a_1, b);
-        return TRUE;
+    MAT3eval(x, &a_1, b);
+    return TRUE;
 }
 
 
@@ -839,3 +839,7 @@
        VEC3scaleAndCut(&r -> v[1], &v -> v[1], d);
        VEC3scaleAndCut(&r -> v[2], &v -> v[2], d);
 }
+
+
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -74,7 +74,7 @@
                 NewElements *= 2;
 
         size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * NewElements);
-        TheNewList = (LPcmsNAMEDCOLORLIST) malloc(size);
+        TheNewList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
 
 
         if (TheNewList == NULL) {
@@ -86,7 +86,7 @@
               CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR));
               TheNewList -> Allocated = NewElements;
 
-              free(v);
+              _cmsFree(v);
               return TheNewList;
         }
     }
@@ -99,7 +99,7 @@
 {
     size_t size = sizeof(cmsNAMEDCOLORLIST) + (n - 1) * sizeof(cmsNAMEDCOLOR);
 
-    LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) malloc(size);
+    LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
 
 
     if (v == NULL) {
@@ -124,10 +124,10 @@
         return;
     }
 
-    free(v);
+    _cmsFree(v);
 }
 
-BOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS])
+LCMSBOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS])
 {
     _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
     LPcmsNAMEDCOLORLIST List;
@@ -146,6 +146,7 @@
         List ->List[List ->nColors].PCS[i] = PCS[i];
 
     strncpy(List ->List[List ->nColors].Name, Name, MAX_PATH-1);
+    List ->List[List ->nColors].Name[MAX_PATH-1] = 0;
 
     List ->nColors++;
     return TRUE;
@@ -164,18 +165,17 @@
 }
 
 
-BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix)
+LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix)
 {
     _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 
-
      if (v ->NamedColorList == NULL) return FALSE;
 
      if (nColor < 0 || nColor >= cmsNamedColorCount(xform)) return FALSE;
 
-     if (Name) strncpy(Name, v ->NamedColorList->List[nColor].Name, 31);
-     if (Prefix) strncpy(Prefix, v ->NamedColorList->Prefix, 31);
-     if (Suffix) strncpy(Suffix, v ->NamedColorList->Suffix, 31);
+         if (Name)   { strncpy(Name, v ->NamedColorList->List[nColor].Name, 31); Name[31] = 0; }
+         if (Prefix) { strncpy(Prefix, v ->NamedColorList->Prefix, 31); Prefix[31] = 0; }
+         if (Suffix) { strncpy(Suffix, v ->NamedColorList->Suffix, 31); Suffix[31] = 0; }
 
      return TRUE;
 }
@@ -196,3 +196,5 @@
 
         return -1;
 }
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Wed Jul 05 16:50:32 2017 +0200
@@ -28,7 +28,7 @@
 // file:
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -639,9 +639,81 @@
 
 
 
+static
+LPBYTE UnrollDouble1Chan(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
+{
+    double* Inks = (double*) accum;
+    double v;
+
+
+    v = floor(Inks[0] * 65535.0 + 0.5);
+
+    if (v > 65535.0) v = 65535.0;
+    if (v < 0) v = 0;
+
+
+    wIn[0] = wIn[1] = wIn[2] = (WORD) v;
+
+    return accum + sizeof(double);
+}
+
+
 // ----------------------------------------------------------- Packing routines
 
 
+// Generic N-bytes plus dither 16-to-8 conversion. Currently is just a quick hack
+
+static int err[MAXCHANNELS];
+
+static
+LPBYTE PackNBytesDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
+{
+       int nChan  = T_CHANNELS(info -> OutputFormat);
+       register int i;
+       unsigned int n, pe, pf;
+
+       for (i=0; i < nChan;  i++) {
+
+              n = wOut[i] + err[i]; // Value
+
+              pe = (n / 257);       // Whole part
+              pf = (n % 257);       // Fractional part
+
+              err[i] = pf;          // Store it for next pixel
+
+              *output++ = (BYTE) pe;
+       }
+
+       return output + T_EXTRA(info ->OutputFormat);
+}
+
+
+
+static
+LPBYTE PackNBytesSwapDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
+{
+       int nChan  = T_CHANNELS(info -> OutputFormat);
+       register int i;
+       unsigned int n, pe, pf;
+
+       for (i=nChan-1; i >= 0;  --i) {
+
+              n = wOut[i] + err[i];     // Value
+
+              pe = (n / 257);           // Whole part
+              pf = (n % 257);           // Fractional part
+
+              err[i] = pf;              // Store it for next pixel
+
+              *output++ = (BYTE) pe;
+       }
+
+
+       return output + T_EXTRA(info ->OutputFormat);
+}
+
+
+
 // Generic chunky for byte
 
 static
@@ -1486,7 +1558,10 @@
            case PT_HSV:
            case PT_HLS:
            case PT_Yxy:
-                    FromInput = UnrollDouble;
+                    if (T_CHANNELS(dwInput) == 1)
+                        FromInput = UnrollDouble1Chan;
+                    else
+                        FromInput = UnrollDouble;
                     break;
 
             // Inks (%) 0.0 .. 100.0
@@ -1749,6 +1824,9 @@
                      switch (T_CHANNELS(dwOutput))
                      {
                      case 1:
+                            if (T_DITHER(dwOutput))
+                                    ToOutput = PackNBytesDither;
+                            else
                             ToOutput = Pack1Byte;
                             if (T_EXTRA(dwOutput) == 1) {
                                 if (T_SWAPFIRST(dwOutput))
@@ -1766,8 +1844,12 @@
                                  else
                                      if (T_COLORSPACE(dwOutput) == PT_Lab)
                                         ToOutput = Pack3BytesLab;
+                                     else {
+                                         if (T_DITHER(dwOutput))
+                                                 ToOutput = PackNBytesDither;
                                      else
                                         ToOutput = Pack3Bytes;
+                                     }
                              break;
 
                          case 1:    // TODO: ALab8 should be handled here
@@ -1793,13 +1875,23 @@
 
                      case 4: if (T_EXTRA(dwOutput) == 0) {
 
+
                                 if (T_DOSWAP(dwOutput)) {
 
-                                     if (T_SWAPFIRST(dwOutput))
+
+                                     if (T_SWAPFIRST(dwOutput)) {
                                          ToOutput = Pack4BytesSwapSwapFirst;
-                                     else
+                                     }
+                                     else {
+
+                                           if (T_DITHER(dwOutput)) {
+                                                  ToOutput = PackNBytesSwapDither;
+                                           }
+                                           else {
                                          ToOutput = Pack4BytesSwap;
                                  }
+                                     }
+                                 }
                                  else {
                                      if (T_SWAPFIRST(dwOutput))
                                          ToOutput = Pack4BytesSwapFirst;
@@ -1807,11 +1899,15 @@
 
                                          if (T_FLAVOR(dwOutput))
                                              ToOutput = Pack4BytesReverse;
+                                         else {
+                                             if (T_DITHER(dwOutput))
+                                                 ToOutput = PackNBytesDither;
                                          else
                                              ToOutput = Pack4Bytes;
                                      }
                                  }
                              }
+                             }
                             else {
                                     if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
                                              ToOutput = PackNBytes;
@@ -1833,7 +1929,7 @@
                             }
                             break;
 
-                                         case 2:
+                     case 2:
                      case 5:
                      case 7:
                      case 8:
@@ -1849,8 +1945,13 @@
                             {
                                    if (T_DOSWAP(dwOutput))
                                           ToOutput = PackNBytesSwap;
+                                   else {
+
+                                       if (T_DITHER(dwOutput))
+                                                 ToOutput = PackNBytesDither;
                                    else
                                           ToOutput = PackNBytes;
+                                   }
                             }
                             break;
 
@@ -1984,7 +2085,7 @@
                             break;
 
 
-                                         case 2:
+                     case 2:
                      case 5:
                      case 7:
                      case 8:
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -624,3 +624,7 @@
     fXYZ -> Z = XYZ2float(XYZ[2]);
 
 }
+
+
+
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -144,6 +144,8 @@
             /Table [ p p p [<...>]]
             /RangeABC [ 0 1 0 1 0 1]
             /DecodeABC[ <postlinearization> ]
+            /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]
+               % -128/500 1+127/500 0 1  -127/200 1+128/200
             /MatrixABC [ 1 1 1 1 0 0 0 0 -1]
             /WhitePoint [D50]
             /BlackPoint [BP]
@@ -347,7 +349,8 @@
 static
 LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols)
 {
-    LPMEMSTREAM m = (LPMEMSTREAM) malloc(sizeof(MEMSTREAM));
+    LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM));
+    if (m == NULL) return NULL;
 
     ZeroMemory(m, sizeof(MEMSTREAM));
 
@@ -376,9 +379,9 @@
 static
 BYTE L2Byte(WORD w)
 {
-        int ww = w + 0x0080;
+    int ww = w + 0x0080;
 
-        if (ww > 0xFFFF) return 0xFF;
+    if (ww > 0xFFFF) return 0xFF;
 
     return (BYTE) ((WORD) (ww >> 8) & 0xFF);
 }
@@ -387,7 +390,6 @@
 static
 void WriteRawByte(LPMEMSTREAM m, BYTE b)
 {
-
     if (m -> dwUsed + 1 > m -> dwMax) {
         m -> HasError = 1;
     }
@@ -422,7 +424,7 @@
 
 }
 
-// Does write a formatted string
+// Does write a formatted string. Guaranteed to be 2048 bytes at most.
 static
 void Writef(LPMEMSTREAM m, const char *frm, ...)
 {
@@ -432,7 +434,7 @@
 
         va_start(args, frm);
 
-        vsprintf((char*) Buffer, frm, args);
+        vsnprintf((char*) Buffer, 2048, frm, args);
 
         for (pt = Buffer; *pt; pt++)  {
 
@@ -562,7 +564,7 @@
     Writef(m, "{255 mul 128 sub 200 div } bind\n");
     Writef(m, "]\n");
     Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
-        Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
+    Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
     Writef(m, "/DecodeLMN [\n");
     Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
     Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
@@ -584,7 +586,11 @@
     if (nEntries <= 0) return;  // Empty table
 
     // Suppress whole if identity
-    if (cmsIsLinear(Table, nEntries)) return;
+    if (cmsIsLinear(Table, nEntries)) {
+            Writef(m, "{} ");
+            return;
+    }
+
 
     // Check if is really an exponential. If so, emit "exp"
      gamma = cmsEstimateGammaEx(Table, nEntries, 0.001);
@@ -646,7 +652,7 @@
 // Compare gamma table
 
 static
-BOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
+LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
 {
     return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;
 }
@@ -676,7 +682,7 @@
 // Check whatever a profile has CLUT tables (only on input)
 
 static
-BOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
+LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
 {
     icTagSignature Tag;
 
@@ -718,10 +724,10 @@
 
     if (sc -> FixWhite) {
 
-        if (In[0] == 0xFFFF) {  // Only in L* = 100
+        if (In[0] == 0xFFFF) {  // Only in L* = 100, ab = [-8..8]
 
-            if ((In[1] >= 0x8000 && In[1] <= 0x87FF) ||
-                (In[2] >= 0x8000 && In[2] <= 0x87FF)) {
+            if ((In[1] >= 0x7800 && In[1] <= 0x8800) &&
+                (In[2] >= 0x7800 && In[2] <= 0x8800)) {
 
                 WORD* Black;
                 WORD* White;
@@ -829,8 +835,8 @@
     sc.PreMaj = PreMaj;
     sc.PostMaj= PostMaj;
 
-    sc.PreMin = PreMin;
-    sc.PostMin= PostMin;
+    sc.PreMin   = PreMin;
+    sc.PostMin  = PostMin;
     sc.lIsInput = lIsInput;
     sc.FixWhite = FixWhite;
     sc.ColorSpace = ColorSpace;
@@ -1231,7 +1237,7 @@
 
         if (!WriteNamedColorCSA(mem, hProfile, Intent)) {
 
-                    free((void*) mem);
+                    _cmsFree((void*) mem);
                     return 0;
         }
     }
@@ -1246,7 +1252,7 @@
         ColorSpace != icSigLabData) {
 
             cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space");
-            free((void*) mem);
+            _cmsFree((void*) mem);
             return 0;
     }
 
@@ -1256,7 +1262,7 @@
         // Yes, so handle as LUT-based
         if (!WriteInputLUT(mem, hProfile, Intent)) {
 
-                    free((void*) mem);
+                    _cmsFree((void*) mem);
                     return 0;
         }
     }
@@ -1266,7 +1272,7 @@
 
         if (!WriteInputMatrixShaper(mem, hProfile)) {
 
-                    free((void*) mem);  // Something went wrong
+                    _cmsFree((void*) mem);  // Something went wrong
                     return 0;
         }
     }
@@ -1277,7 +1283,7 @@
     dwBytesUsed = mem ->dwUsed;
 
     // Get rid of memory stream
-    free((void*) mem);
+    _cmsFree((void*) mem);
 
     // Finally, return used byte count
     return dwBytesUsed;
@@ -1350,27 +1356,40 @@
 
 
 static
-void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute)
+void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
 {
 
 
+        if (lIsAbsolute) {
+
+            // For absolute colorimetric intent, encode back to relative
+            // and generate a relative LUT
+
+            // Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
+
+            cmsCIEXYZ White;
+
+            cmsTakeMediaWhitePoint(&White, hProfile);
+
+            Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
+            Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
+
+            Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
+                      "/TransformPQR [\n"
+                      "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n"
+                      "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n"
+                      "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n",
+                      White.X, White.Y, White.Z);
+            return;
+        }
+
+
         Writef(m,"%% Bradford Cone Space\n"
                  "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
 
         Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
 
 
-        if (lIsAbsolute) {
-
-            // For absolute colorimetric intent, do nothing
-
-            Writef(m, "%% Absolute colorimetric -- no transformation\n"
-                      "/TransformPQR [\n"
-                      "{exch pop exch pop exch pop exch pop} bind dup dup]\n");
-            return;
-        }
-
-
         // No BPC
 
         if (!DoBPC) {
@@ -1414,6 +1433,7 @@
 static
 void EmitXYZ2Lab(LPMEMSTREAM m)
 {
+    Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
     Writef(m, "/EncodeLMN [\n");
     Writef(m, "{ 0.964200  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
     Writef(m, "{ 1.000000  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
@@ -1423,17 +1443,10 @@
     Writef(m, "/EncodeABC [\n");
 
 
-
     Writef(m, "{ 116 mul  16 sub 100 div  } bind\n");
-    Writef(m, "{ 500 mul 128 add 255 div  } bind\n");
-    Writef(m, "{ 200 mul 128 add 255 div  } bind\n");
-
+    Writef(m, "{ 500 mul 128 add 256 div  } bind\n");
+    Writef(m, "{ 200 mul 128 add 256 div  } bind\n");
 
-    /*
-    Writef(m, "{ 116 mul  16 sub 256 mul 25700 div  } bind\n");
-    Writef(m, "{ 500 mul 128 add 256 mul 65535 div  } bind\n");
-    Writef(m, "{ 200 mul 128 add 256 mul 65535 div  } bind\n");
-    */
 
     Writef(m, "]\n");
 
@@ -1458,20 +1471,27 @@
     LPLUT DeviceLink;
     cmsHPROFILE Profiles[3];
     cmsCIEXYZ BlackPointAdaptedToD50;
-    BOOL lFreeDeviceLink = FALSE;
-    BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
+    LCMSBOOL lFreeDeviceLink = FALSE;
+    LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
+    LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
+    int RelativeEncodingIntent;
 
 
-    // Trick our v4 profile as it were v2. This prevents the ajusting done
-    // in perceptual & saturation. We only neew v4 encoding!
 
-    hLab         = cmsCreateLab4Profile(NULL);
-    cmsSetProfileICCversion(hLab, 0);
+    hLab = cmsCreateLabProfile(NULL);
 
     ColorSpace  =  cmsGetColorSpace(hProfile);
     nChannels   = _cmsChannelsOf(ColorSpace);
     OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
 
+    // For absolute colorimetric, the LUT is encoded as relative
+    // in order to preserve precission.
+
+    RelativeEncodingIntent = Intent;
+    if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC)
+        RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC;
+
+
     // Is a devicelink profile?
     if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
 
@@ -1479,13 +1499,14 @@
 
         if (ColorSpace == icSigLabData) {
 
-              // adjust input to Lab to out v4
+              // adjust input to Lab to our v4
 
             Profiles[0] = hLab;
             Profiles[1] = hProfile;
 
             xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL,
-                                                        OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
+                                                        OutputFormat, RelativeEncodingIntent,
+                                                        dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
 
         }
         else {
@@ -1499,7 +1520,7 @@
 
         // This is a normal profile
         xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile,
-                            OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
+                            OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
     }
 
     if (xform == NULL) {
@@ -1515,7 +1536,7 @@
 
     if (!DeviceLink) {
 
-        DeviceLink = _cmsPrecalculateDeviceLink(xform, 0);
+        DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION);
         lFreeDeviceLink = TRUE;
     }
 
@@ -1527,7 +1548,7 @@
 
     // Emit headers, etc.
     EmitWhiteBlackD50(m, &BlackPointAdaptedToD50);
-    EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
+    EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
     EmitXYZ2Lab(m);
 
     if (DeviceLink ->wFlags & LUT_HASTL1) {
@@ -1544,10 +1565,13 @@
     // zero. This would sacrifice a bit of highlights, but failure to do so would cause
     // scum dot. Ouch.
 
+    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
+            lFixWhite = FALSE;
+
     Writef(m, "/RenderTable ");
 
     WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE,
-                (Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace);
+                lFixWhite, ColorSpace);
 
     Writef(m, " %d {} bind ", nChannels);
 
@@ -1582,6 +1606,9 @@
     int j;
 
     Colorant[0] = 0;
+    if (nColorant > MAXCHANNELS)
+        nColorant = MAXCHANNELS;
+
     for (j=0; j < nColorant; j++) {
 
                 sprintf(Buff, "%.3f", Out[j] / 65535.0);
@@ -1677,7 +1704,7 @@
 
         if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) {
 
-                    free((void*) mem);
+                    _cmsFree((void*) mem);
                     return 0;
         }
     }
@@ -1687,7 +1714,7 @@
 
 
     if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
-        free((void*) mem);
+        _cmsFree((void*) mem);
         return 0;
     }
     }
@@ -1702,7 +1729,7 @@
     dwBytesUsed = mem ->dwUsed;
 
     // Get rid of memory stream
-    free((void*) mem);
+    _cmsFree((void*) mem);
 
     // Finally, return used byte count
     return dwBytesUsed;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -120,7 +120,7 @@
 // This routine does a sweep on whole input space, and calls its callback
 // function on knots. returns TRUE if all ok, FALSE otherwise.
 
-BOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags)
+LCMSBOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags)
 {
    int i, t, nTotalPoints, Colorant, index;
    WORD In[MAXCHANNELS], Out[MAXCHANNELS];
@@ -145,12 +145,16 @@
                                                 &Lut -> In16params);
         }
 
+        for (t=0; t < (int) Lut -> OutputChan; t++)
+                     Out[t] = Lut->T[index + t];
 
-        // if (dwFlags & SAMPLER_INSPECT) {
+        if (dwFlags & SAMPLER_HASTL2) {
 
              for (t=0; t < (int) Lut -> OutputChan; t++)
-                        Out[t] = Lut->T[index + t];
-        // }
+                     Out[t] = cmsLinearInterpLUT16(Out[t],
+                                                   Lut -> L2[t],
+                                                   &Lut -> Out16params);
+        }
 
 
         if (!Sampler(In, Out, Cargo))
@@ -255,9 +259,11 @@
        LPLUT Grid;
        int nGridPoints;
        DWORD dwFormatIn, dwFormatOut;
+       DWORD SaveFormatIn, SaveFormatOut;
        int ChannelsIn, ChannelsOut;
        LPLUT SaveGamutLUT;
 
+
        // Remove any gamut checking
        SaveGamutLUT = p ->Gamut;
        p ->Gamut = NULL;
@@ -276,8 +282,13 @@
        dwFormatIn   = (CHANNELS_SH(ChannelsIn)|BYTES_SH(2));
        dwFormatOut  = (CHANNELS_SH(ChannelsOut)|BYTES_SH(2));
 
-       p -> FromInput = _cmsIdentifyInputFormat(p, dwFormatIn);
-       p -> ToOutput  = _cmsIdentifyOutputFormat(p, dwFormatOut);
+       SaveFormatIn  = p ->InputFormat;
+       SaveFormatOut = p ->OutputFormat;
+
+       p -> InputFormat  = dwFormatIn;
+       p -> OutputFormat = dwFormatOut;
+       p -> FromInput    = _cmsIdentifyInputFormat(p, dwFormatIn);
+       p -> ToOutput     = _cmsIdentifyOutputFormat(p, dwFormatOut);
 
        // Fix gamut & gamma possible mismatches.
 
@@ -289,7 +300,6 @@
            _cmsComputePrelinearizationTablesFromXFORM(hOne, 1, Grid);
        }
 
-
        // Attention to this typecast! we can take the luxury to
        // do this since cmsHTRANSFORM is only an alias to a pointer
        // to the transform struct.
@@ -297,11 +307,13 @@
        if (!cmsSample3DGrid(Grid, XFormSampler, (LPVOID) p, Grid -> wFlags)) {
 
                 cmsFreeLUT(Grid);
-                return NULL;
+                Grid = NULL;
        }
 
+       p ->Gamut        = SaveGamutLUT;
+       p ->InputFormat  = SaveFormatIn;
+       p ->OutputFormat = SaveFormatOut;
 
-       p ->Gamut = SaveGamutLUT;
        return Grid;
 }
 
@@ -348,7 +360,7 @@
 
 
 
-// That is our K-preserving callback.
+// Preserve all K plane.
 static
 int BlackPreservingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 {
@@ -469,6 +481,7 @@
     return OldVal;
 }
 
+#pragma warning(disable: 4550)
 
 // Get a pointer to callback on depending of strategy
 static
@@ -504,11 +517,10 @@
        if (p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)
            LocalFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
 
-
        // Fill in cargo struct
        Cargo.cmyk2cmyk = hCMYK2CMYK;
 
-       // Compute tone curve
+       // Compute tone curve.
        Cargo.KTone  =  _cmsBuildKToneCurve(hCMYK2CMYK, 256);
        if (Cargo.KTone == NULL) return NULL;
        cmsCalcL16Params(Cargo.KTone ->nEntries, &Cargo.KToneParams);
@@ -522,11 +534,11 @@
        Cargo.LabK2cmyk = cmsReadICCLut(p->OutputProfile, Device2PCS[p->Intent]);
 
        // Is there any table available?
-           if (Cargo.LabK2cmyk == NULL) {
+       if (Cargo.LabK2cmyk == NULL) {
 
-                   Grid = NULL;
+           Grid = NULL;
            goto Cleanup;
-           }
+       }
 
        // Setup a roundtrip on output profile for TAC estimation
        Cargo.hRoundTrip = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16,
@@ -654,7 +666,7 @@
 
 
 
-BOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
+LCMSBOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
 {
 
        WORD *WhitePointIn, *WhitePointOut, *BlackPointIn, *BlackPointOut;
@@ -682,3 +694,4 @@
 
        return TRUE;
 }
+
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -320,7 +320,7 @@
     cmsHPROFILE hICC;
     _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) hTransform;
     LPLUT Lut;
-    BOOL MustFreeLUT;
+    LCMSBOOL MustFreeLUT;
     LPcmsNAMEDCOLORLIST InputColorant = NULL;
     LPcmsNAMEDCOLORLIST OutputColorant = NULL;
 
@@ -373,10 +373,8 @@
 
     if (cmsGetDeviceClass(hICC) == icSigOutputClass) {
 
-
         cmsAddTag(hICC, icSigBToA0Tag, (LPVOID) Lut);
     }
-
     else
         cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
 
@@ -404,7 +402,7 @@
 
             OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableTag);
         }
-        }
+    }
 
     if (InputColorant)
            cmsAddTag(hICC, icSigColorantTableTag, InputColorant);
@@ -446,6 +444,7 @@
 
        // Creates a LUT with prelinearization step only
        Lut = cmsAllocLUT();
+       if (Lut == NULL) return NULL;
 
        // Set up channels
        Lut ->InputChan = Lut ->OutputChan = _cmsChannelsOf(ColorSpace);
@@ -548,6 +547,10 @@
 
        // Creates a LUT with 3D grid only
        Lut = cmsAllocLUT();
+       if (Lut == NULL) {
+           cmsCloseProfile(hICC);
+           return NULL;
+           }
 
 
        cmsAlloc3DGrid(Lut, 17, _cmsChannelsOf(ColorSpace),
@@ -584,8 +587,9 @@
 LPLUT Create3x3EmptyLUT(void)
 {
         LPLUT AToB0 = cmsAllocLUT();
+        if (AToB0 == NULL) return NULL;
+
         AToB0 -> InputChan = AToB0 -> OutputChan = 3;
-
         return AToB0;
 }
 
@@ -597,8 +601,8 @@
         cmsHPROFILE hProfile;
         LPLUT Lut;
 
-
         hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
+        if (hProfile == NULL) return NULL;
 
         cmsSetDeviceClass(hProfile, icSigAbstractClass);
         cmsSetColorSpace(hProfile,  icSigLabData);
@@ -611,7 +615,10 @@
 
        // An empty LUTs is all we need
        Lut = Create3x3EmptyLUT();
-       if (Lut == NULL) return NULL;
+       if (Lut == NULL) {
+           cmsCloseProfile(hProfile);
+           return NULL;
+           }
 
        cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
        cmsAddTag(hProfile, icSigBToA0Tag,    (LPVOID) Lut);
@@ -628,8 +635,8 @@
         cmsHPROFILE hProfile;
         LPLUT Lut;
 
-
         hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
+        if (hProfile == NULL) return NULL;
 
         cmsSetProfileICCversion(hProfile, 0x4000000);
 
@@ -644,7 +651,10 @@
 
        // An empty LUTs is all we need
        Lut = Create3x3EmptyLUT();
-       if (Lut == NULL) return NULL;
+       if (Lut == NULL) {
+           cmsCloseProfile(hProfile);
+           return NULL;
+           }
 
        Lut -> wFlags |= LUT_V4_INPUT_EMULATE_V2;
        cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
@@ -666,6 +676,7 @@
         LPLUT Lut;
 
         hProfile = cmsCreateRGBProfile(cmsD50_xyY(), NULL, NULL);
+        if (hProfile == NULL) return NULL;
 
         cmsSetDeviceClass(hProfile, icSigAbstractClass);
         cmsSetColorSpace(hProfile, icSigXYZData);
@@ -677,15 +688,16 @@
 
        // An empty LUTs is all we need
        Lut = Create3x3EmptyLUT();
-       if (Lut == NULL) return NULL;
+       if (Lut == NULL) {
+           cmsCloseProfile(hProfile);
+           return NULL;
+           }
 
        cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
        cmsAddTag(hProfile, icSigBToA0Tag,    (LPVOID) Lut);
        cmsAddTag(hProfile, icSigPreview0Tag, (LPVOID) Lut);
 
        cmsFreeLUT(Lut);
-
-
        return hProfile;
 }
 
@@ -723,6 +735,7 @@
     return cmsBuildParametricGamma(1024, 4, Parameters);
 }
 
+// Create the ICC virtual profile for sRGB space
 cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void)
 {
        cmsCIExyY       D65;
@@ -739,6 +752,7 @@
 
        hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma22);
        cmsFreeGamma(Gamma22[0]);
+       if (hsRGB == NULL) return NULL;
 
 
        cmsAddTag(hsRGB, icSigDeviceMfgDescTag,      (LPVOID) "(lcms internal)");
@@ -750,7 +764,6 @@
 
 
 
-
 typedef struct {
                 double Brightness;
                 double Contrast;
@@ -793,7 +806,6 @@
 
     cmsFloat2LabEncoded(Out, &LabOut);
 
-
     return TRUE;
 }
 
@@ -839,7 +851,10 @@
 
        // Creates a LUT with 3D grid only
        Lut = cmsAllocLUT();
-
+       if (Lut == NULL) {
+           cmsCloseProfile(hICC);
+           return NULL;
+           }
 
        cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3);
 
@@ -890,7 +905,10 @@
 
        // An empty LUTs is all we need
        Lut = cmsAllocLUT();
-       if (Lut == NULL) return NULL;
+       if (Lut == NULL) {
+           cmsCloseProfile(hProfile);
+           return NULL;
+           }
 
        Lut -> InputChan = 3;
        Lut -> OutputChan = 1;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -51,10 +51,6 @@
 
 #include "lcms.h"
 
-// Uncomment this line if you want lcms to use the black point tag in profile,
-// if commented, lcms will compute the black point by its own.
-// It is safer to leve it commented out
-// #define HONOR_BLACK_POINT_TAG
 
 // Conversions
 
@@ -79,10 +75,9 @@
 }
 
 
-
 // Obtains WhitePoint from Temperature
 
-BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
+LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
 {
        double x, y;
        double T, T2, T3;
@@ -147,7 +142,7 @@
 //            - Then, I apply these coeficients to the original matrix
 
 
-BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
+LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
                                             LPcmsCIExyYTRIPLE Primrs)
 {
         VEC3 WhitePoint, Coef;
@@ -169,14 +164,12 @@
 
 
         // Build Primaries matrix
-
         VEC3init(&Primaries.v[0], xr,        xg,         xb);
         VEC3init(&Primaries.v[1], yr,        yg,         yb);
         VEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg),  (1-xb-yb));
 
 
         // Result = Primaries ^ (-1) inverse matrix
-
         if (!MAT3inverse(&Primaries, &Result))
                         return FALSE;
 
@@ -184,11 +177,9 @@
         VEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
 
         // Across inverse primaries ...
-
         MAT3eval(&Coef, &Result, &WhitePoint);
 
         // Give us the Coefs, then I build transformation matrix
-
         VEC3init(&r -> v[0], Coef.n[VX]*xr,          Coef.n[VY]*xg,          Coef.n[VZ]*xb);
         VEC3init(&r -> v[1], Coef.n[VX]*yr,          Coef.n[VY]*yg,          Coef.n[VZ]*yb);
         VEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
@@ -246,7 +237,7 @@
 // Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll
 // The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed
 
-BOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll)
+LCMSBOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll)
 {
      MAT3 LamRigg   = {{ // Bradford matrix
                       {{  0.8951,  0.2664, -0.1614 }},
@@ -265,7 +256,7 @@
 
 // Same as anterior, but assuming D50 destination. White point is given in xyY
 
-BOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
+LCMSBOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
 {
         cmsCIEXYZ Dn;
         MAT3 Bradford;
@@ -284,7 +275,7 @@
 
 // Same as anterior, but assuming D50 source. White point is given in xyY
 
-BOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
+LCMSBOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
 {
         cmsCIEXYZ Dn;
         MAT3 Bradford;
@@ -304,7 +295,7 @@
 // Adapts a color to a given illuminant. Original color is expected to have
 // a SourceWhitePt white point.
 
-BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
+LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
                                      LPcmsCIEXYZ SourceWhitePt,
                                      LPcmsCIEXYZ Illuminant,
                                      LPcmsCIEXYZ Value)
@@ -404,8 +395,6 @@
 
         dj = ((vs - vj) - tj * (us - uj)) / sqrt(1 + tj*tj);
 
-
-
         if ((j!=0) && (di/dj < 0.0)) {
             Tc = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
             break;
@@ -423,7 +412,7 @@
 
 
 static
-BOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance)
+LCMSBOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance)
 {
        double dist_x, dist_y;
 
@@ -458,6 +447,7 @@
 }
 
 
+// To be removed in future versions
 void _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt)
 {
        int i, n;
@@ -518,7 +508,6 @@
     cmsCIEXYZ  BlackXYZ, MediaWhite;
 
     // If the profile does not support input direction, assume Black point 0
-
     if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {
 
         BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
@@ -527,7 +516,6 @@
 
 
     // Try to get black by using black colorant
-
     Space = cmsGetColorSpace(hInput);
 
     if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) {
@@ -576,7 +564,7 @@
 
 
 // Get a black point of output CMYK profile, discounting any ink-limiting embedded
-// in the profile. Fou doing that, use perceptual intent in input direction:
+// in the profile. For doing that, use perceptual intent in input direction:
 // Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
 
 static
@@ -651,6 +639,8 @@
             D50BlackPoint.X = PERCEPTUAL_BLACK_X;
             D50BlackPoint.Y = PERCEPTUAL_BLACK_Y;
             D50BlackPoint.Z = PERCEPTUAL_BLACK_Z;
+
+            // Obtain the absolute XYZ. Adapt perceptual black back from D50 to whatever media white
             cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &D50BlackPoint);
         }
 
@@ -662,26 +652,24 @@
 // This function shouldn't exist at all -- there is such quantity of broken
 // profiles on black point tag, that we must somehow fix chromaticity to
 // avoid huge tint when doing Black point compensation. This function does
-// just that. If BP is specified, then forces it to neutral and uses only L
-// component. If does not exist, computes it by taking 400% of ink or RGB=0 This
-// works well on relative intent and is undefined on perceptual & saturation.
-// However, I will support all intents for tricking & trapping.
-
+// just that. There is a special flag for using black point tag, but turned
+// off by default because it is bogus on most profiles. The detection algorithm
+// involves to turn BP to neutral and to use only L component.
 
 int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags)
 {
 
-    // v4 + perceptual & saturation intents does have its own black point
+    // v4 + perceptual & saturation intents does have its own black point, and it is
+    // well specified enough to use it.
 
     if ((cmsGetProfileICCversion(hProfile) >= 0x4000000) &&
         (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
 
        // Matrix shaper share MRC & perceptual intents
-
        if (_cmsIsMatrixShaper(hProfile))
            return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, cmsFLAGS_NOTPRECALC);
 
-       // Get fixed value
+       // CLUT based - Get perceptual black point (fixed value)
        return GetV4PerceptualBlack(BlackPoint, hProfile, dwFlags);
     }
 
@@ -701,7 +689,6 @@
              cmsTakeMediaWhitePoint(&MediaWhite, hProfile);
 
              // Black point is absolute XYZ, so adapt to D50 to get PCS value
-
              cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ);
 
              // Force a=b=0 to get rid of any chroma
@@ -713,7 +700,6 @@
              cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab);
 
              // Return BP as D50 relative or absolute XYZ (depends on flags)
-
              if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED))
                     cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &TrustedBlackPoint);
              else
@@ -724,15 +710,15 @@
 
 #endif
 
-    // If output profile, discount ink-limiting
+    // That is about v2 profiles.
 
+    // If output profile, discount ink-limiting and that's all
     if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
             (cmsGetDeviceClass(hProfile) == icSigOutputClass) &&
             (cmsGetColorSpace(hProfile) == icSigCmykData))
                 return BlackPointUsingPerceptualBlack(BlackPoint, hProfile, dwFlags);
 
     // Nope, compute BP using current intent.
-
     return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags);
 
 }
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,6 @@
 
 #include "lcms.h"
 
-// #define DEBUG 1
 
 // Transformations stuff
 // -----------------------------------------------------------------------
@@ -85,7 +84,7 @@
 
 void         LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b);
 void         LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b);
-BOOL         LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
+LCMSBOOL     LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
                                                 int Intent, int UsedDirection);
 
 // -------------------------------------------------------------------------
@@ -343,7 +342,7 @@
            p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
                                     p ->DeviceLink -> T,
                                     &p ->DeviceLink -> CLut16params);
-                 }
+         }
          else
             cmsEvalLUT(p -> DeviceLink, wIn, wOut);
 
@@ -414,7 +413,7 @@
        register LPBYTE output;
        WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
        register unsigned int i, n;
-           WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
+       WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
 
 
        accum  = (LPBYTE) in;
@@ -427,10 +426,10 @@
        ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
 
 
-           LCMS_READ_LOCK(&p ->rwlock);
-               CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
-               CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
-           LCMS_UNLOCK(&p ->rwlock);
+       LCMS_READ_LOCK(&p ->rwlock);
+           CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
+           CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
+       LCMS_UNLOCK(&p ->rwlock);
 
        for (i=0; i < n; i++) {
 
@@ -443,14 +442,14 @@
        }
        else {
 
-                        // Try to speedup things on plain devicelinks
-
-                         if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
+            // Try to speedup things on plain devicelinks
+
+             if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
 
              p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
                                     p ->DeviceLink -> T,
                                     &p ->DeviceLink -> CLut16params);
-                     }
+             }
              else
                   cmsEvalLUT(p -> DeviceLink, wIn, wOut);
 
@@ -463,10 +462,10 @@
        }
 
 
-           LCMS_WRITE_LOCK(&p ->rwlock);
-               CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
-               CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
-           LCMS_UNLOCK(&p ->rwlock);
+       LCMS_WRITE_LOCK(&p ->rwlock);
+           CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
+           CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
+       LCMS_UNLOCK(&p ->rwlock);
 
 }
 
@@ -483,7 +482,7 @@
        register LPBYTE output;
        WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
        register unsigned int i, n;
-           WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
+       WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
 
 
        accum  = (LPBYTE) in;
@@ -495,10 +494,10 @@
        ZeroMemory(wIn,  sizeof(WORD) * MAXCHANNELS);
        ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
 
-           LCMS_READ_LOCK(&p ->rwlock);
-               CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
-               CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
-           LCMS_UNLOCK(&p ->rwlock);
+       LCMS_READ_LOCK(&p ->rwlock);
+           CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
+           CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
+       LCMS_UNLOCK(&p ->rwlock);
 
 
        for (i=0; i < n; i++) {
@@ -520,10 +519,10 @@
        output = p -> ToOutput(p, wOut, output);
        }
 
-            LCMS_WRITE_LOCK(&p ->rwlock);
-               CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
-               CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
-            LCMS_UNLOCK(&p ->rwlock);
+        LCMS_WRITE_LOCK(&p ->rwlock);
+           CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
+           CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
+        LCMS_UNLOCK(&p ->rwlock);
 }
 
 
@@ -635,6 +634,8 @@
        MAT3 Scale;
 
        GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag);        // Y
+       if (GrayTRC == NULL) return NULL;
+
        cmsTakeIluminant(&Illuminant, hProfile);
 
        if (cmsGetPCS(hProfile) == icSigLabData) {
@@ -789,6 +790,10 @@
        InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag);
        InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag);
 
+       if (InverseShapes[0] == NULL ||
+           InverseShapes[1] == NULL ||
+           InverseShapes[2] == NULL) return NULL;
+
        OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT);
 
        cmsFreeGammaTriple(InverseShapes);
@@ -801,7 +806,7 @@
 // This function builds a transform matrix chaining parameters
 
 static
-BOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
+LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
 {
        MAT3 From, To, ToInv, Transfer;
        LPGAMMATABLE In[3], InverseOut[3];
@@ -814,7 +819,6 @@
        if (!cmsReadICCMatrixRGB2XYZ(&To, p -> OutputProfile))
                      return FALSE;
 
-
        // invert dest
 
        if (MAT3inverse(&To, &ToInv) < 0)
@@ -838,10 +842,14 @@
         InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag);
         InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag);
 
+        if (!InverseOut[0] || !InverseOut[1] || !InverseOut[2]) {
+                     cmsFreeGammaTriple(In);
+                     return FALSE;
+        }
+
         p -> SmeltMatShaper = cmsAllocMatShaper2(&Transfer, In, InverseOut, MATSHAPER_ALLSMELTED);
 
         cmsFreeGammaTriple(In);
-
         cmsFreeGammaTriple(InverseOut);
 
         return (p -> SmeltMatShaper != NULL);
@@ -1029,7 +1037,7 @@
 // Check colorspace
 
 static
-BOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, BOOL lUsePCS)
+LCMSBOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, LCMSBOOL lUsePCS)
 {
        int Space = T_COLORSPACE(dwFormat);
 
@@ -1049,10 +1057,10 @@
 {
     // Allocate needed memory
 
-    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) malloc(sizeof(_cmsTRANSFORM));
+    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) _cmsMalloc(sizeof(_cmsTRANSFORM));
     if (!p) {
 
-          cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: malloc() failed");
+          cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: _cmsMalloc() failed");
           return NULL;
     }
 
@@ -1078,7 +1086,7 @@
     p -> ExitColorSpace  = (icColorSpaceSignature) 0;
     p -> AdaptationState = GlobalAdaptationState;
 
-        LCMS_CREATE_LOCK(&p->rwlock);
+    LCMS_CREATE_LOCK(&p->rwlock);
 
     return p;
 }
@@ -1269,12 +1277,12 @@
         else {
                 // Can we optimize matrix-shaper only transform?
 
-                   if (*FromTagPtr == 0 &&
-                       *ToTagPtr == 0 &&
-                       !p->PreviewProfile  &&
-                       p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC &&
+                   if ((*FromTagPtr == 0) &&
+                       (*ToTagPtr == 0) &&
+                       (!p->PreviewProfile) &&
+                       (p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
                        (p -> EntryColorSpace == icSigRgbData) &&
-                       (p -> ExitColorSpace == icSigRgbData) &&
+                       (p -> ExitColorSpace == icSigRgbData)  &&
                        !(p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)) {
 
                           // Yes... try to smelt matrix-shapers
@@ -1530,7 +1538,6 @@
 
        TakeConversionRoutines(p, dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
 
-
        if (!(p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
 
                LPLUT DeviceLink;
@@ -1553,7 +1560,8 @@
                     DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
                }
 
-               if (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK) {
+               // Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given
+               if ((p ->PreviewProfile != NULL) && (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK)) {
 
                    GamutCheck = _cmsPrecalculateGamutCheck((cmsHTRANSFORM) p);
                }
@@ -1561,7 +1569,6 @@
                // If input colorspace is Rgb, Cmy, then use tetrahedral interpolation
                // for speed reasons (it only works well on spaces on Luma is diagonal, and
                // not if luma is in separate channel)
-
                if (p ->EntryColorSpace == icSigRgbData ||
                    p ->EntryColorSpace == icSigCmyData) {
 
@@ -1663,12 +1670,12 @@
               cmsFreeMatShaper(p -> SmeltMatShaper);
        if (p ->NamedColorList)
               cmsFreeNamedColorList(p ->NamedColorList);
-           if (p -> GamutCheck)
-                        cmsFreeLUT(p -> GamutCheck);
-
-           LCMS_FREE_LOCK(&p->rwlock);
-
-       free((void *) p);
+       if (p -> GamutCheck)
+            cmsFreeLUT(p -> GamutCheck);
+
+       LCMS_FREE_LOCK(&p->rwlock);
+
+       _cmsFree((void *) p);
 }
 
 
@@ -1704,7 +1711,7 @@
 
 // Returns TRUE if the profile is implemented as matrix-shaper
 
-BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
+LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
 {
     switch (cmsGetColorSpace(hProfile)) {
 
@@ -1728,7 +1735,7 @@
 }
 
 
-BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
+LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
                                                 int Intent, int UsedDirection)
 {
 
@@ -1774,6 +1781,16 @@
 }
 
 
+static
+int IsAllowedInSingleXform(icProfileClassSignature aClass)
+{
+    return (aClass == icSigInputClass) ||
+           (aClass == icSigDisplayClass) ||
+           (aClass == icSigOutputClass) ||
+           (aClass == icSigColorSpaceClass);
+}
+
+
 // A multiprofile transform does chain several profiles into a single
 // devicelink. It couls also be used to merge named color profiles into
 // a single database.
@@ -1805,10 +1822,16 @@
     // There is a simple case with just two profiles, try to catch it in order of getting
     // black preservation to work on this function, at least with two profiles.
 
+
     if (nProfiles == 2) {
 
-        if ((cmsGetDeviceClass(hProfiles[0]) != icSigLinkClass) &&
-            (cmsGetDeviceClass(hProfiles[1]) != icSigLinkClass))
+        icProfileClassSignature Class1 = cmsGetDeviceClass(hProfiles[0]);
+        icProfileClassSignature Class2 = cmsGetDeviceClass(hProfiles[1]);
+
+        // Only input, output and display are allowed
+
+        if (IsAllowedInSingleXform(Class1) &&
+            IsAllowedInSingleXform(Class2))
                    return cmsCreateTransform(hProfiles[0], dwInput, hProfiles[1], dwOutput, Intent, dwFlags);
     }
 
@@ -1984,6 +2007,14 @@
     if (hLab) cmsCloseProfile(hLab);
     if (hXYZ) cmsCloseProfile(hXYZ);
 
+
+    if (p ->EntryColorSpace == icSigRgbData ||
+        p ->EntryColorSpace == icSigCmyData) {
+
+                    p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
+    }
+
+
     if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
         !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
                             _cmsFixWhiteMisalignment(p);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h	Wed Jul 05 16:50:32 2017 +0200
@@ -206,6 +206,11 @@
 
 #if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__)
 
+#if defined (__MINGW) || defined(__MINGW32__)
+#include <stdint.h>
+#endif
+
+
 typedef uint8_t   icUInt8Number;
 typedef uint16_t  icUInt16Number;
 typedef uint32_t  icUInt32Number;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h	Wed Jul 05 16:50:32 2017 +0200
@@ -29,7 +29,7 @@
 //
 //
 //  Little cms
-//  Copyright (C) 1998-2006 Marti Maria
+//  Copyright (C) 1998-2007 Marti Maria
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -49,8 +49,8 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-// Version 1.16
-#undef DEBUG
+// Version 1.18
+
 #ifndef __cms_H
 
 // ********** Configuration toggles ****************************************
@@ -62,13 +62,8 @@
 // virtually any machine.
 
 //#define USE_FLOAT        1
-#ifdef _WIN64
-#define USE_C            1
-#undef USE_ASSEMBLER
-#else
-#undef USE_C
+// #define USE_C            1
 #define USE_ASSEMBLER    1
-#endif
 
 // Define this if you are using this package as a DLL (windows only)
 
@@ -77,15 +72,11 @@
 
 // Uncomment if you are trying the engine in a non-windows environment
 // like linux, SGI, VAX, FreeBSD, BeOS, etc.
-#if !defined(_WIN32) || !defined(_WIN64)
 #define NON_WINDOWS  1
-#endif
 
 // Uncomment this one if you are using big endian machines (only meaningful
 // when NON_WINDOWS is used)
-#ifndef _LITTLE_ENDIAN
-#define USE_BIG_ENDIAN   1
-#endif
+// #define USE_BIG_ENDIAN   1
 
 // Uncomment this one if your compiler/machine does support the
 // "long long" type This will speedup fixed point math. (USE_C only)
@@ -104,18 +95,24 @@
 // Uncomment this line on multithreading environments
 // #define USE_PTHREADS    1
 
+// Uncomment this line if you want lcms to use the black point tag in profile,
+// if commented, lcms will compute the black point by its own.
+// It is safer to leve it commented out
+// #define HONOR_BLACK_POINT_TAG    1
+
 // ********** End of configuration toggles ******************************
 
-#define LCMS_VERSION        116
+#define LCMS_VERSION        118
 
 // Microsoft VisualC++
 
 // Deal with Microsoft's attempt at deprecating C standard runtime functions
-
 #ifdef _MSC_VER
 #    undef NON_WINDOWS
 #    if (_MSC_VER >= 1400)
+#      ifndef _CRT_SECURE_NO_DEPRECATE
 #        define _CRT_SECURE_NO_DEPRECATE 1
+#      endif
 #    endif
 #endif
 
@@ -125,7 +122,6 @@
 #    undef NON_WINDOWS
 #endif
 
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
@@ -134,11 +130,11 @@
 #include <time.h>
 
 // Metroworks CodeWarrior
-
 #ifdef __MWERKS__
 #   define unlink remove
 #   if WIN32
 #       define USE_CUSTOM_SWAB 1
+#       undef  NON_WINDOWS
 #   else
 #       define NON_WINDOWS   1
 #   endif
@@ -172,15 +168,21 @@
 #   define USE_BIG_ENDIAN      1
 #endif
 
-#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__)
+#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__) || defined(__s390__) || defined(__s390x__)
 #   define USE_BIG_ENDIAN      1
 #endif
 
-#ifdef TARGET_CPU_PPC
+#if TARGET_CPU_PPC
 #   define USE_BIG_ENDIAN   1
 #endif
 
-#ifdef macintosh
+#if macintosh
+# ifndef __LITTLE_ENDIAN__
+#   define USE_BIG_ENDIAN      1
+# endif
+#endif
+
+#ifdef __BIG_ENDIAN__
 #   define USE_BIG_ENDIAN      1
 #endif
 
@@ -217,11 +219,8 @@
 typedef unsigned char BYTE, *LPBYTE;
 typedef unsigned short WORD, *LPWORD;
 typedef unsigned long DWORD, *LPDWORD;
-typedef int BOOL;
 typedef char *LPSTR;
 typedef void *LPVOID;
-typedef void* LCMSHANDLE;
-
 
 #define ZeroMemory(p,l)     memset((p),0,(l))
 #define CopyMemory(d,s,l)   memcpy((d),(s),(l))
@@ -263,8 +262,12 @@
 
 #include <windows.h>
 
-typedef HANDLE LCMSHANDLE;
-
+#ifdef _WIN64
+# ifdef USE_ASSEMBLER
+#    undef  USE_ASSEMBLER
+#    define USE_C           1
+# endif
+#endif
 
 #ifdef  USE_INT64
 #  ifndef LCMSULONGLONG
@@ -296,6 +299,10 @@
 #   define LCMS_UNLOCK(x)
 #endif
 
+// Base types
+
+typedef int   LCMSBOOL;
+typedef void* LCMSHANDLE;
 
 #include "icc34.h"          // ICC header file
 
@@ -322,16 +329,10 @@
 #define icSigMCHEData                  ((icColorSpaceSignature) 0x4d434845L)  // MCHE
 #define icSigMCHFData                  ((icColorSpaceSignature) 0x4d434846L)  // MCHF
 
-#define icSigCAM97JABData              ((icColorSpaceSignature) 0x4A616231L)  // 'Jab1' H. Zeng
-#define icSigCAM02JABData              ((icColorSpaceSignature) 0x4A616232L)  // 'Jab2' H. Zeng
-#define icSigCAM02JCHData              ((icColorSpaceSignature) 0x4A636A32L)  // 'Jch2' H. Zeng
-
 #define icSigChromaticityTag            ((icTagSignature) 0x6368726dL) // As per Addendum 2 to Spec. ICC.1:1998-09
 #define icSigChromaticAdaptationTag     ((icTagSignature) 0x63686164L) // 'chad'
 #define icSigColorantTableTag           ((icTagSignature) 0x636c7274L) // 'clrt'
 #define icSigColorantTableOutTag        ((icTagSignature) 0x636c6f74L) // 'clot'
-#define icSigHPGamutDescTag             ((icTagSignature) 0x676D7441L) // 'gmtA' H. Zeng
-
 
 #define icSigParametricCurveType        ((icTagTypeSignature) 0x70617261L)  // parametric (ICC 4.0)
 #define icSigMultiLocalizedUnicodeType  ((icTagTypeSignature) 0x6D6C7563L)
@@ -340,7 +341,6 @@
 #define icSiglutAtoBType                ((icTagTypeSignature) 0x6d414220L)  // mAB
 #define icSiglutBtoAType                ((icTagTypeSignature) 0x6d424120L)  // mBA
 #define icSigColorantTableType          ((icTagTypeSignature) 0x636c7274L)  // clrt
-#define icSigHPGamutDescType            ((icTagTypeSignature) 0x676D7441L)  // gmtA H. Zeng
 
 
 typedef struct {
@@ -438,9 +438,6 @@
 #ifndef itoa
 #       define itoa   _itoa
 #endif
-#ifndef filelength
-#       define filelength _filelength
-#endif
 #ifndef fileno
 #       define fileno   _fileno
 #endif
@@ -450,6 +447,14 @@
 #ifndef hypot
 #       define hypot    _hypot
 #endif
+#ifndef snprintf
+#       define snprintf  _snprintf
+#endif
+#ifndef vsnprintf
+#       define vsnprintf  _vsnprintf
+#endif
+
+
 #endif
 
 
@@ -470,8 +475,9 @@
 
 // Format of pixel is defined by one DWORD, using bit fields as follows
 //
-//            TTTTT U Y F P X S EEE CCCC BBB
+//            D TTTTT U Y F P X S EEE CCCC BBB
 //
+//            D: Use dither (8 bits only)
 //            T: Pixeltype
 //            F: Flavor  0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla)
 //            P: Planar? 0=Chunky, 1=Planar
@@ -483,6 +489,7 @@
 //            Y: Swap first - changes ABGR to BGRA and KCMY to CMYK
 
 
+#define DITHER_SH(s)           ((s) << 22)
 #define COLORSPACE_SH(s)       ((s) << 16)
 #define SWAPFIRST_SH(s)        ((s) << 14)
 #define FLAVOR_SH(s)           ((s) << 13)
@@ -711,20 +718,20 @@
 
 typedef struct {
 
-        unsigned int Crc32;  // Has my table been touched?
-
-        // Keep initial parameters for further serialization
+    unsigned int Crc32;  // Has my table been touched?
+
+    // Keep initial parameters for further serialization
 
     int          Type;
     double       Params[10];
 
-        }  LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS;
+    }  LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS;
 
 // Gamma tables.
 
 typedef struct {
 
-        LCMSGAMMAPARAMS Seed;   // Parameters used for table creation
+    LCMSGAMMAPARAMS Seed;       // Parameters used for table creation
 
     // Table-based representation follows
 
@@ -858,7 +865,7 @@
 
 LCMSAPI cmsHPROFILE   LCMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess);
 LCMSAPI cmsHPROFILE   LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize);
-LCMSAPI BOOL          LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
 
 // Predefined run-time profiles
 
@@ -915,14 +922,14 @@
 
 LCMSAPI void          LCMSEXPORT cmsClampLab(LPcmsCIELab Lab, double amax, double amin, double bmax, double bmin);
 
-LCMSAPI BOOL          LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint);
-
-LCMSAPI BOOL          LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint);
+
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
                                                         LPcmsCIEXYZ SourceWhitePt,
                                                         LPcmsCIEXYZ Illuminant,
                                                         LPcmsCIEXYZ Value);
 
-LCMSAPI BOOL          LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r,
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r,
                                                         LPcmsCIExyY WhitePoint,
                                                         LPcmsCIExyYTRIPLE Primaries);
 
@@ -976,7 +983,7 @@
 LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma);
 LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma,  LPGAMMATABLE OutGamma);
 LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma,  LPGAMMATABLE OutGamma, int nPoints);
-LCMSAPI BOOL          LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
 LCMSAPI double        LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t);
 LCMSAPI double        LCMSEXPORT cmsEstimateGammaEx(LPWORD Table, int nEntries, double Thereshold);
 LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig);
@@ -984,14 +991,14 @@
 
 // Access to Profile data.
 
-LCMSAPI BOOL          LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
-LCMSAPI BOOL          LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
-LCMSAPI BOOL          LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
-LCMSAPI BOOL          LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile);
 LCMSAPI DWORD         LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile);
 LCMSAPI DWORD         LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile);
 
-LCMSAPI void          LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode);
+LCMSAPI void          LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4]);
 LCMSAPI const char*   LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile);
 LCMSAPI const char*   LCMSEXPORT cmsTakeProductDesc(cmsHPROFILE hProfile);
 LCMSAPI const char*   LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile);
@@ -1000,13 +1007,13 @@
 LCMSAPI const char*   LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile);
 LCMSAPI const BYTE*   LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile);
 
-LCMSAPI BOOL          LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
-LCMSAPI BOOL          LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
-
-LCMSAPI BOOL          LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
+
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig);
 LCMSAPI int           LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile);
 
-LCMSAPI BOOL          LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len);
+LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len);
 
 LCMSAPI int           LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Text, size_t size);
 LCMSAPI int           LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Text);
@@ -1038,50 +1045,18 @@
 LCMSAPI void          LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq);
 
 
-// Extended gamut tag -- an HP extension
-
-#define LCMSGAMUTMETHOD_SEGMENTMAXIMA   0
-#define LCMSGAMUTMETHOD_CONVEXHULL      1
-#define LCMSGAMUTMETHOD_ALPHASHAPE      2
-
-
-#define LCMSGAMUT_PHYSICAL                              0
-#define LCMSGAMUT_HP1                                   1
-#define LCMSGAMUT_HP2                                   2
-
-typedef struct {
-
-                        icColorSpaceSignature  CoordSig;        // Gamut coordinates signature
-                        icUInt16Number         Method;          // Method used to generate gamut
-                        icUInt16Number         Usage;       // Gamut usage or intent
-
-                        char Description[LCMS_DESC_MAX];        // Textual description
-
-                        cmsViewingConditions   Vc;                      // The viewing conditions
-
-                        icUInt32Number         Count;           // Number of entries
-                        double                             Data[1];         // The current data
-
-        } cmsGAMUTEX, FAR* LPcmsGAMUTEX;
-
-
-LCMSAPI LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index);
-LCMSAPI void         LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex);
-
-
-
-
 // Translate form/to our notation to ICC
 LCMSAPI icColorSpaceSignature LCMSEXPORT _cmsICCcolorSpace(int OurNotation);
-LCMSAPI                   int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace);
-LCMSAPI                   int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace);
-LCMSAPI BOOL                  LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile);
-
+LCMSAPI int                   LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace);
+LCMSAPI int                   LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace);
+LCMSAPI LCMSBOOL              LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile);
+
+// How profiles may be used
 #define LCMS_USED_AS_INPUT      0
 #define LCMS_USED_AS_OUTPUT     1
 #define LCMS_USED_AS_PROOF      2
 
-LCMSAPI BOOL         LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
+LCMSAPI LCMSBOOL                LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
 
 LCMSAPI icColorSpaceSignature   LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile);
 LCMSAPI icColorSpaceSignature   LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile);
@@ -1141,7 +1116,7 @@
 
 // CRD special
 
-#define cmsFLAGS_NODEFAULTRESOURCEDEF     0x00010000
+#define cmsFLAGS_NODEFAULTRESOURCEDEF     0x01000000
 
 // Gridpoints
 
@@ -1220,9 +1195,9 @@
 
 // Named color support
 
-LCMSAPI int  LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform);
-LCMSAPI BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix);
-LCMSAPI int  LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name);
+LCMSAPI int      LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform);
+LCMSAPI LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix);
+LCMSAPI int      LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name);
 
 // Colorant tables
 
@@ -1230,7 +1205,7 @@
 
 // Profile creation
 
-LCMSAPI BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data);
+LCMSAPI LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data);
 
 // Converts a transform to a devicelink profile
 LCMSAPI cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags);
@@ -1240,8 +1215,8 @@
 
 
 // Save profile
-LCMSAPI BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName);
-LCMSAPI BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
+LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName);
+LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
                                                                 size_t* BytesNeeded);
 
 
@@ -1286,6 +1261,7 @@
 LCMSAPI LPLUT  LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig);
 LCMSAPI LPLUT  LCMSEXPORT cmsDupLUT(LPLUT Orig);
 
+
 // LUT Sampling
 
 typedef int (* _cmsSAMPLER)(register WORD In[],
@@ -1325,35 +1301,37 @@
 // Persistence
 LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
 LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded);
 
 // Properties
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
-
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
-
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
-
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
+
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
+
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
 
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
 LCMSAPI double          LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
-LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames);
+LCMSAPI const char*     LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
+LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames);
+LCMSAPI int             LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
 
 // Datasets
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
 LCMSAPI double          LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int row, int col);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
                                                 const char* Val);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
                                                 double Val);
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
@@ -1361,25 +1339,28 @@
 
 LCMSAPI double          LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
                                                 const char* cSample,
                                                 const char *Val);
 
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
                                                 const char* cSample,
                                                 double Val);
 
 LCMSAPI int             LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample);
-LCMSAPI BOOL            LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
 LCMSAPI int             LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
 
 
 LCMSAPI const char*     LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer);
+LCMSAPI int             LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cSample);
 
 // The LABEL extension
 
 LCMSAPI int             LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType);
 
+LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample);
+
 // Formatter for double
 LCMSAPI void            LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
 
@@ -1405,15 +1386,16 @@
 
 // Profiling Extensions --- Would be removed from API in future revisions
 
-LCMSAPI BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile,  icTagSignature sig, const char* Text);
-LCMSAPI BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile,   icTagSignature sig, const cmsCIEXYZ* XYZ);
-LCMSAPI BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile,   icTagSignature sig, const void* lut);
-LCMSAPI BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction);
-LCMSAPI BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm);
-LCMSAPI BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq);
-LCMSAPI BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
-LCMSAPI BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime);
-LCMSAPI BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile,  icTagSignature sig, const char* Text);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile,   icTagSignature sig, const cmsCIEXYZ* XYZ);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile,   icTagSignature sig, const void* lut);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
+LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat);
 
 // --------------------------------------------------------------------------------------------------- Inline functions
 
@@ -1455,6 +1437,38 @@
        return (WORD) in;
 }
 
+#ifndef LCMS_USER_ALLOC
+
+// Low-level alloc hook
+
+LCMS_INLINE void* _cmsMalloc(size_t size)
+{
+    if (size > ((size_t) 1024*1024*500)) return NULL;  // Never allow over 500Mb
+    if (size < 0) return NULL;              // Prevent signed size_t exploits
+
+    return (void*) malloc(size);
+}
+
+LCMS_INLINE void* _cmsCalloc(size_t nmemb, size_t size)
+{
+    size_t alloc = nmemb * size;
+
+        if (size == 0) {
+                return _cmsMalloc(0);
+        }
+        if (alloc / size != nmemb) {
+        return NULL;
+    }
+    return _cmsMalloc(alloc);
+}
+
+LCMS_INLINE void _cmsFree(void *Ptr)
+{
+    if (Ptr) free(Ptr);
+}
+
+#endif
+
 // ------------------------------------------------------------------------------------------- end of inline functions
 
 // Signal error from inside lcms code
@@ -1531,36 +1545,36 @@
 
 
 
-void   cdecl VEC3init(LPVEC3 r, double x, double y, double z);   // double version
-void   cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version
-void   cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
-void   cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v);
-void   cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
-void   cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
-void   cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
-void   cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
-void   cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
-void   cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
-BOOL   cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance);
-BOOL   cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance);
-void   cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
-void   cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
-void   cdecl VEC3saturate(LPVEC3 v);
-double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
-double cdecl VEC3length(LPVEC3 a);
-
-void   cdecl MAT3identity(LPMAT3 a);
-void   cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
-void   cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
-int    cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
-BOOL   cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
-double cdecl MAT3det(LPMAT3 m);
-void   cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
-void   cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
-void   cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v);
-void   cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
-BOOL   cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance);
-void   cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
+void      cdecl VEC3init(LPVEC3 r, double x, double y, double z);   // double version
+void      cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version
+void      cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
+void      cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v);
+void      cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
+void      cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
+void      cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
+void      cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
+void      cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
+void      cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
+LCMSBOOL  cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance);
+LCMSBOOL  cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance);
+void      cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
+void      cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
+void      cdecl VEC3saturate(LPVEC3 v);
+double    cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
+double    cdecl VEC3length(LPVEC3 a);
+
+void      cdecl MAT3identity(LPMAT3 a);
+void      cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
+void      cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
+int       cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
+LCMSBOOL  cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
+double    cdecl MAT3det(LPMAT3 m);
+void      cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
+void      cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
+void      cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v);
+void      cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
+LCMSBOOL  cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance);
+void      cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
 
 // Is a table linear?
 
@@ -1608,7 +1622,7 @@
 void    cdecl cmsCalcL16Params(int nSamples, LPL16PARAMS p);
 void    cdecl cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p);
 void    cdecl cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
-                                            BOOL lUseTetrahedral, LPL16PARAMS p);
+                                            LCMSBOOL lUseTetrahedral, LPL16PARAMS p);
 
 WORD    cdecl cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p);
 Fixed32 cdecl cmsLinearInterpFixed(WORD Value1, WORD LutTable[], LPL16PARAMS p);
@@ -1692,18 +1706,18 @@
 
                // Gray axes fixup. Only on v2 8-bit Lab LUT
 
-               BOOL FixGrayAxes;
-
-
-                           // Parameters used for curve creation
-
-                           LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS];
+               LCMSBOOL FixGrayAxes;
+
+
+               // Parameters used for curve creation
+
+               LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS];
 
 
                }; // LUT, FAR* LPLUT;
 
 
-BOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries);
+LCMSBOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries);
 
 
 // CRC of gamma tables
@@ -1721,7 +1735,7 @@
 
 void           cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
 void           cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
-BOOL           cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
+LCMSBOOL       cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
 void           cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
 
 LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
@@ -1755,19 +1769,19 @@
 void        cdecl cmsFreeMatShaper(LPMATSHAPER MatShaper);
 void        cdecl cmsEvalMatShaper(LPMATSHAPER MatShaper, WORD In[], WORD Out[]);
 
-BOOL         cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile);
-
-LPMATSHAPER  cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile);
-LPMATSHAPER  cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile);
+LCMSBOOL    cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile);
+
+LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile);
+LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile);
 
 
 
 // White Point & Primary chromas handling
-BOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll);
-BOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt);
-BOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt);
-
-BOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile);
+LCMSBOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll);
+LCMSBOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt);
+LCMSBOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt);
+
+LCMSBOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile);
 
 // Inter-PCS conversion routines. They assume D50 as white point.
 void cdecl cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3]);
@@ -1782,7 +1796,7 @@
 LPcmsNAMEDCOLORLIST  cdecl cmsAllocNamedColorList(int n);
 int                  cdecl cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSignature sig);
 void                 cdecl cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST List);
-BOOL                 cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]);
+LCMSBOOL             cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]);
 
 
 // I/O
@@ -1804,7 +1818,7 @@
                icColorSpaceSignature   PCS;
                icRenderingIntent       RenderingIntent;
                icUInt32Number          flags;
-                           icUInt32Number          attributes;
+               icUInt32Number          attributes;
                cmsCIEXYZ               Illuminant;
 
                // Additions for V4 profiles
@@ -1826,22 +1840,23 @@
 
                char                    PhysicalFile[MAX_PATH];
 
-               BOOL                    IsWrite;
-               BOOL                    SaveAs8Bits;
+               LCMSBOOL                IsWrite;
+               LCMSBOOL                SaveAs8Bits;
 
                struct tm               Created;
 
                // I/O handlers
 
-               size_t (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc);
-
-               BOOL   (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
-               BOOL   (* Close)(struct _lcms_iccprofile_struct* Icc);
-               size_t (* Tell)(struct _lcms_iccprofile_struct* Icc);
+               size_t   (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc);
+
+               LCMSBOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
+               LCMSBOOL (* Close)(struct _lcms_iccprofile_struct* Icc);
+               size_t   (* Tell)(struct _lcms_iccprofile_struct* Icc);
+               LCMSBOOL  (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount);
 
                // Writting
 
-               BOOL   (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr);
+               LCMSBOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr);
 
                size_t UsedSpace;
 
@@ -1853,7 +1868,7 @@
 cmsHPROFILE cdecl _cmsCreateProfilePlaceholder(void);
 
 // Search into tag dictionary
-icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError);
+icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError);
 
 // Search for a particular tag, replace if found or add new one else
 LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init);
@@ -1869,6 +1884,7 @@
 
 // These macros unpack format specifiers into integers
 
+#define T_DITHER(s)           (((s)>>22)&1)
 #define T_COLORSPACE(s)       (((s)>>16)&31)
 #define T_SWAPFIRST(s)        (((s)>>14)&1)
 #define T_FLAVOR(s)           (((s)>>13)&1)
@@ -1965,7 +1981,7 @@
 
                     // Flag for transform involving v4 profiles
 
-                    BOOL lInputV4Lab, lOutputV4Lab;
+                    LCMSBOOL lInputV4Lab, lOutputV4Lab;
 
 
                     // 1-pixel cache
@@ -1975,7 +1991,7 @@
 
                     double AdaptationState; // Figure for v4 incomplete state of adaptation
 
-                                        LCMS_RWLOCK_T rwlock;
+                    LCMS_RWLOCK_T rwlock;
 
                    } _cmsTRANSFORM,FAR *_LPcmsTRANSFORM;
 
@@ -2012,7 +2028,7 @@
 
 // Clamping & Gamut handling
 
-BOOL cdecl   _cmsEndPointsBySpace(icColorSpaceSignature Space,
+LCMSBOOL cdecl   _cmsEndPointsBySpace(icColorSpaceSignature Space,
                             WORD **White, WORD **Black, int *nOutputs);
 
 WORD * cdecl _cmsWhiteBySpace(icColorSpaceSignature Space);
@@ -2041,7 +2057,7 @@
 LPLUT cdecl _cmsPrecalculateGamutCheck(cmsHTRANSFORM h);
 
 // Hot fixes bad profiles
-BOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p);
+LCMSBOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p);
 
 // Marks LUT as 8 bit on input
 LPLUT cdecl _cmsBlessLUT8(LPLUT Lut);
@@ -2059,6 +2075,10 @@
 // Build a tone curve for K->K' if possible (only works on CMYK)
 LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
 
+// Validates a LUT
+LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT);
+
+
 // These are two VITAL macros, from converting between 8 and 16 bit
 // representation.
 
@@ -2076,3 +2096,4 @@
 #endif
 
 #endif
+
--- a/jdk/src/solaris/classes/sun/awt/X11/XFontPeer.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XFontPeer.java	Wed Jul 05 16:50:32 2017 +0200
@@ -27,9 +27,6 @@
 import sun.awt.PlatformFont;
 import java.awt.GraphicsEnvironment;
 
-/* FIX ME */
-import sun.awt.motif.MFontConfiguration;
-
 public class XFontPeer extends PlatformFont {
 
     /*
@@ -51,10 +48,6 @@
 
     public XFontPeer(String name, int style){
         super(name, style);
-
-        if (fontConfig != null){
-            xfsname = ((MFontConfiguration) fontConfig).getMotifFontSet(familyName, style);
-        }
     }
 
     protected char getMissingGlyphCharacter() {
--- a/jdk/src/solaris/classes/sun/font/FcFontConfiguration.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/solaris/classes/sun/font/FcFontConfiguration.java	Wed Jul 05 16:50:32 2017 +0200
@@ -15,7 +15,7 @@
  * accompanied this code).
  *
  * You should have received a copy of the GNU General Public License version
- * along with this work; if not, write to the Free Software Foundation,
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
@@ -87,6 +87,7 @@
             return true;
         }
 
+        setFontConfiguration();
         readFcInfo();
         if (fcCompFonts == null) {
             fcCompFonts = FontManager.loadFontConfig();
@@ -172,7 +173,7 @@
 
     @Override
     public FontDescriptor[] getFontDescriptors(String fontName, int style) {
-        throw new InternalError("Not implemented");
+        return new FontDescriptor[0];
     }
 
     @Override
--- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java	Wed Jul 05 16:50:32 2017 +0200
@@ -661,6 +661,12 @@
                 }
             }
         } else if (category == OrientationRequested.class) {
+            if (flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
+                flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
+                flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT)) {
+                return null;
+            }
+
             boolean revPort = false;
             OrientationRequested[] orientSup = null;
 
--- a/jdk/src/solaris/classes/sun/print/UnixPrintJob.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintJob.java	Wed Jul 05 16:50:32 2017 +0200
@@ -362,10 +362,10 @@
                  mOptions += " number-up="+nUp.getValue();
              }
 
-             if (orient == OrientationRequested.LANDSCAPE &&
+             if (orient != OrientationRequested.PORTRAIT &&
                  (flavor != null) &&
                  !flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {
-                 mOptions += " landscape";
+                 mOptions += " orientation-requested="+orient.getValue();
              }
 
              if (sides != null) {
--- a/jdk/src/windows/classes/sun/awt/windows/WFontConfiguration.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WFontConfiguration.java	Wed Jul 05 16:50:32 2017 +0200
@@ -61,18 +61,10 @@
              * been opened and its fonts loaded.
              * Also note this usage is only enabled if a private flag is set.
              */
-            if ("98".equals(osName) || "Me".equals(osName)) {
-                localeMap.put("dialoginput.plain.japanese", "\uff2d\uff33 \u660e\u671d");
-                localeMap.put("dialoginput.bold.japanese", "\uff2d\uff33 \u660e\u671d");
-                localeMap.put("dialoginput.italic.japanese", "\uff2d\uff33 \u660e\u671d");
-                localeMap.put("dialoginput.bolditalic.japanese", "\uff2d\uff33 \u660e\u671d");
-            } else {
-
-                localeMap.put("dialoginput.plain.japanese", "MS Mincho");
-                localeMap.put("dialoginput.bold.japanese", "MS Mincho");
-                localeMap.put("dialoginput.italic.japanese", "MS Mincho");
-                localeMap.put("dialoginput.bolditalic.japanese", "MS Mincho");
-            }
+            localeMap.put("dialoginput.plain.japanese", "MS Mincho");
+            localeMap.put("dialoginput.bold.japanese", "MS Mincho");
+            localeMap.put("dialoginput.italic.japanese", "MS Mincho");
+            localeMap.put("dialoginput.bolditalic.japanese", "MS Mincho");
         }
         reorderMap = new HashMap();
         reorderMap.put("UTF-8.hi", "devanagari");
--- a/jdk/src/windows/classes/sun/awt/windows/fontconfig.98.properties	Thu Apr 02 16:51:48 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-#
-# 
-# Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
-# 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.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-
-# Version
-
-version=1
-
-# Component Font Mappings
-
-allfonts.chinese-ms936=SimSun
-allfonts.dingbats=Wingdings
-allfonts.lucida=Lucida Sans Regular
-allfonts.symbol=Symbol
-allfonts.thai=Lucida Sans Regular
-
-serif.plain.alphabetic=Times New Roman
-serif.plain.chinese-ms950=MingLiU
-serif.plain.hebrew=David
-serif.plain.japanese=\uff2d\uff33 \u660e\u671d
-serif.plain.korean=Batang
-
-serif.bold.alphabetic=Times New Roman Bold
-serif.bold.chinese-ms950=PMingLiU
-serif.bold.hebrew=David Bold
-serif.bold.japanese=\uff2d\uff33 \u660e\u671d
-serif.bold.korean=Batang
-
-serif.italic.alphabetic=Times New Roman Italic
-serif.italic.chinese-ms950=PMingLiU
-serif.italic.hebrew=David
-serif.italic.japanese=\uff2d\uff33 \u660e\u671d
-serif.italic.korean=Batang
-
-serif.bolditalic.alphabetic=Times New Roman Bold Italic
-serif.bolditalic.chinese-ms950=PMingLiU
-serif.bolditalic.hebrew=David Bold
-serif.bolditalic.japanese=\uff2d\uff33 \u660e\u671d
-serif.bolditalic.korean=Batang
-
-sansserif.plain.alphabetic=Arial
-sansserif.plain.chinese-ms950=MingLiU
-sansserif.plain.hebrew=David
-sansserif.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.plain.korean=Gulim
-
-sansserif.bold.alphabetic=Arial Bold
-sansserif.bold.chinese-ms950=PMingLiU
-sansserif.bold.hebrew=David Bold
-sansserif.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.bold.korean=Gulim
-
-sansserif.italic.alphabetic=Arial Italic
-sansserif.italic.chinese-ms950=PMingLiU
-sansserif.italic.hebrew=David
-sansserif.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.italic.korean=Gulim
-
-sansserif.bolditalic.alphabetic=Arial Bold Italic
-sansserif.bolditalic.chinese-ms950=PMingLiU
-sansserif.bolditalic.hebrew=David Bold
-sansserif.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.bolditalic.korean=Gulim
-
-monospaced.plain.alphabetic=Courier New
-monospaced.plain.chinese-ms950=MingLiU
-monospaced.plain.hebrew=David
-monospaced.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.plain.korean=GulimChe
-
-monospaced.bold.alphabetic=Courier New Bold
-monospaced.bold.chinese-ms950=PMingLiU
-monospaced.bold.hebrew=David Bold
-monospaced.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.bold.korean=GulimChe
-
-monospaced.italic.alphabetic=Courier New Italic
-monospaced.italic.chinese-ms950=PMingLiU
-monospaced.italic.hebrew=David
-monospaced.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.italic.korean=GulimChe
-
-monospaced.bolditalic.alphabetic=Courier New Bold Italic
-monospaced.bolditalic.chinese-ms950=PMingLiU
-monospaced.bolditalic.hebrew=David Bold
-monospaced.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.bolditalic.korean=GulimChe
-
-dialog.plain.alphabetic=Arial
-dialog.plain.chinese-ms950=MingLiU
-dialog.plain.hebrew=David
-dialog.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.plain.korean=Gulim
-
-dialog.bold.alphabetic=Arial Bold
-dialog.bold.chinese-ms950=PMingLiU
-dialog.bold.hebrew=David Bold
-dialog.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.bold.korean=Gulim
-
-dialog.italic.alphabetic=Arial Italic
-dialog.italic.chinese-ms950=PMingLiU
-dialog.italic.hebrew=David
-dialog.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.italic.korean=Gulim
-
-dialog.bolditalic.alphabetic=Arial Bold Italic
-dialog.bolditalic.chinese-ms950=PMingLiU
-dialog.bolditalic.hebrew=David Bold
-dialog.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.bolditalic.korean=Gulim
-
-dialoginput.plain.alphabetic=Courier New
-dialoginput.plain.chinese-ms950=MingLiU
-dialoginput.plain.hebrew=David
-dialoginput.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.plain.korean=Gulim
-
-dialoginput.bold.alphabetic=Courier New Bold
-dialoginput.bold.chinese-ms950=PMingLiU
-dialoginput.bold.hebrew=David Bold
-dialoginput.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.bold.korean=Gulim
-
-dialoginput.italic.alphabetic=Courier New Italic
-dialoginput.italic.chinese-ms950=PMingLiU
-dialoginput.italic.hebrew=David
-dialoginput.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.italic.korean=Gulim
-
-dialoginput.bolditalic.alphabetic=Courier New Bold Italic
-dialoginput.bolditalic.chinese-ms950=PMingLiU
-dialoginput.bolditalic.hebrew=David Bold
-dialoginput.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.bolditalic.korean=Gulim
-
-# Search Sequences
-
-sequence.allfonts=alphabetic/default,dingbats,symbol
-
-sequence.serif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.sansserif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.monospaced.GBK=chinese-ms936,alphabetic/1252,dingbats,symbol
-sequence.dialog.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.dialoginput.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-
-sequence.serif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.sansserif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.monospaced.x-windows-950=chinese-ms950,alphabetic/1252,dingbats,symbol
-sequence.dialog.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.dialoginput.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-
-sequence.allfonts.windows-1255=hebrew,alphabetic/1252,dingbats,symbol
-
-sequence.serif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.sansserif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.monospaced.windows-31j=japanese,alphabetic/1252,dingbats,symbol
-sequence.dialog.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.dialoginput.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-
-sequence.serif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.sansserif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.monospaced.x-windows-949=korean,alphabetic/1252,dingbats,symbol
-sequence.dialog.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.dialoginput.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-
-sequence.allfonts.x-windows-874=alphabetic/1252,thai,dingbats,symbol
-
-sequence.fallback=lucida
-
-# Exclusion Ranges
-
-exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
-exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
-
-# Monospaced to Proportional width variant mapping
-# (Experimental private syntax)
-proportional.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af
-proportional.\uff2d\uff33_\u660e\u671d=\uff2d\uff33 \uff30\u660e\u671d
-proportional.MingLiU=PMingLiU
-
-# Font File Names
-
-filename.Arial=ARIAL.TTF
-filename.Arial_Bold=ARIALBD.TTF
-filename.Arial_Italic=ARIALI.TTF
-filename.Arial_Bold_Italic=ARIALBI.TTF
-
-filename.Courier_New=COUR.TTF
-filename.Courier_New_Bold=COURBD.TTF
-filename.Courier_New_Italic=COURI.TTF
-filename.Courier_New_Bold_Italic=COURBI.TTF
-
-filename.Times_New_Roman=TIMES.TTF
-filename.Times_New_Roman_Bold=TIMESBD.TTF
-filename.Times_New_Roman_Italic=TIMESI.TTF
-filename.Times_New_Roman_Bold_Italic=TIMESBI.TTF
-
-filename.SimSun=SIMSUN.TTF
-
-filename.MingLiU=MINGLIU.TTC
-filename.PMingLiU=MINGLIU.TTC
-
-filename.David=DAVID.TTF
-filename.David_Bold=DAVIDBD.TTF
-
-filename.\uff2d\uff33_\u660e\u671d=MSMINCHO.TTC
-filename.\uff2d\uff33_\uff30\u660e\u671d=MSMINCHO.TTC
-filename.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
-filename.\uff2d\uff33_\uff30\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
-
-filename.Gulim=gulim.TTC
-filename.Batang=batang.TTC
-filename.GulimChe=gulim.TTC
-
-filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
-filename.Symbol=SYMBOL.TTF
-filename.Wingdings=WINGDING.TTF
-
--- a/jdk/src/windows/classes/sun/awt/windows/fontconfig.Me.properties	Thu Apr 02 16:51:48 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-#
-# 
-# Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
-# 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.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-
-# Version
-
-version=1
-
-# Component Font Mappings
-
-allfonts.chinese-ms936=SimSun
-allfonts.dingbats=Wingdings
-allfonts.lucida=Lucida Sans Regular
-allfonts.symbol=Symbol
-allfonts.thai=Lucida Sans Regular
-
-serif.plain.alphabetic=Times New Roman
-serif.plain.chinese-ms950=MingLiU
-serif.plain.hebrew=David
-serif.plain.japanese=\uff2d\uff33 \u660e\u671d
-serif.plain.korean=Batang
-
-serif.bold.alphabetic=Times New Roman Bold
-serif.bold.chinese-ms950=PMingLiU
-serif.bold.hebrew=David Bold
-serif.bold.japanese=\uff2d\uff33 \u660e\u671d
-serif.bold.korean=Batang
-
-serif.italic.alphabetic=Times New Roman Italic
-serif.italic.chinese-ms950=PMingLiU
-serif.italic.hebrew=David
-serif.italic.japanese=\uff2d\uff33 \u660e\u671d
-serif.italic.korean=Batang
-
-serif.bolditalic.alphabetic=Times New Roman Bold Italic
-serif.bolditalic.chinese-ms950=PMingLiU
-serif.bolditalic.hebrew=David Bold
-serif.bolditalic.japanese=\uff2d\uff33 \u660e\u671d
-serif.bolditalic.korean=Batang
-
-sansserif.plain.alphabetic=Arial
-sansserif.plain.chinese-ms950=MingLiU
-sansserif.plain.hebrew=David
-sansserif.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.plain.korean=Gulim
-
-sansserif.bold.alphabetic=Arial Bold
-sansserif.bold.chinese-ms950=PMingLiU
-sansserif.bold.hebrew=David Bold
-sansserif.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.bold.korean=Gulim
-
-sansserif.italic.alphabetic=Arial Italic
-sansserif.italic.chinese-ms950=PMingLiU
-sansserif.italic.hebrew=David
-sansserif.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.italic.korean=Gulim
-
-sansserif.bolditalic.alphabetic=Arial Bold Italic
-sansserif.bolditalic.chinese-ms950=PMingLiU
-sansserif.bolditalic.hebrew=David Bold
-sansserif.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-sansserif.bolditalic.korean=Gulim
-
-monospaced.plain.alphabetic=Courier New
-monospaced.plain.chinese-ms950=MingLiU
-monospaced.plain.hebrew=David
-monospaced.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.plain.korean=GulimChe
-
-monospaced.bold.alphabetic=Courier New Bold
-monospaced.bold.chinese-ms950=PMingLiU
-monospaced.bold.hebrew=David Bold
-monospaced.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.bold.korean=GulimChe
-
-monospaced.italic.alphabetic=Courier New Italic
-monospaced.italic.chinese-ms950=PMingLiU
-monospaced.italic.hebrew=David
-monospaced.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.italic.korean=GulimChe
-
-monospaced.bolditalic.alphabetic=Courier New Bold Italic
-monospaced.bolditalic.chinese-ms950=PMingLiU
-monospaced.bolditalic.hebrew=David Bold
-monospaced.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-monospaced.bolditalic.korean=GulimChe
-
-dialog.plain.alphabetic=Arial
-dialog.plain.chinese-ms950=MingLiU
-dialog.plain.hebrew=David
-dialog.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.plain.korean=Gulim
-
-dialog.bold.alphabetic=Arial Bold
-dialog.bold.chinese-ms950=PMingLiU
-dialog.bold.hebrew=David Bold
-dialog.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.bold.korean=Gulim
-
-dialog.italic.alphabetic=Arial Italic
-dialog.italic.chinese-ms950=PMingLiU
-dialog.italic.hebrew=David
-dialog.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.italic.korean=Gulim
-
-dialog.bolditalic.alphabetic=Arial Bold Italic
-dialog.bolditalic.chinese-ms950=PMingLiU
-dialog.bolditalic.hebrew=David Bold
-dialog.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialog.bolditalic.korean=Gulim
-
-dialoginput.plain.alphabetic=Courier New
-dialoginput.plain.chinese-ms950=MingLiU
-dialoginput.plain.hebrew=David
-dialoginput.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.plain.korean=Gulim
-
-dialoginput.bold.alphabetic=Courier New Bold
-dialoginput.bold.chinese-ms950=PMingLiU
-dialoginput.bold.hebrew=David Bold
-dialoginput.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.bold.korean=Gulim
-
-dialoginput.italic.alphabetic=Courier New Italic
-dialoginput.italic.chinese-ms950=PMingLiU
-dialoginput.italic.hebrew=David
-dialoginput.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.italic.korean=Gulim
-
-dialoginput.bolditalic.alphabetic=Courier New Bold Italic
-dialoginput.bolditalic.chinese-ms950=PMingLiU
-dialoginput.bolditalic.hebrew=David Bold
-dialoginput.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
-dialoginput.bolditalic.korean=Gulim
-
-# Search Sequences
-
-sequence.allfonts=alphabetic/default,dingbats,symbol
-
-sequence.serif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.sansserif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.monospaced.GBK=chinese-ms936,alphabetic/1252,dingbats,symbol
-sequence.dialog.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-sequence.dialoginput.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
-
-sequence.serif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.sansserif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.monospaced.x-windows-950=chinese-ms950,alphabetic/1252,dingbats,symbol
-sequence.dialog.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-sequence.dialoginput.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
-
-sequence.allfonts.windows-1255=hebrew,alphabetic/1252,dingbats,symbol
-
-sequence.serif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.sansserif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.monospaced.windows-31j=japanese,alphabetic/1252,dingbats,symbol
-sequence.dialog.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-sequence.dialoginput.windows-31j=alphabetic/1252,japanese,dingbats,symbol
-
-sequence.serif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.sansserif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.monospaced.x-windows-949=korean,alphabetic/1252,dingbats,symbol
-sequence.dialog.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-sequence.dialoginput.x-windows-949=alphabetic/1252,korean,dingbats,symbol
-
-sequence.allfonts.x-windows-874=alphabetic/1252,thai,dingbats,symbol
-
-sequence.fallback=lucida
-
-# Exclusion Ranges
-
-exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
-exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
-
-# Monospaced to Proportional width variant mapping
-# (Experimental private syntax)
-proportional.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af
-proportional.\uff2d\uff33_\u660e\u671d=\uff2d\uff33 \uff30\u660e\u671d
-proportional.MingLiU=PMingLiU
-
-# Font File Names
-
-filename.Arial=ARIAL.TTF
-filename.Arial_Bold=ARIALBD.TTF
-filename.Arial_Italic=ARIALI.TTF
-filename.Arial_Bold_Italic=ARIALBI.TTF
-
-filename.Courier_New=COUR.TTF
-filename.Courier_New_Bold=COURBD.TTF
-filename.Courier_New_Italic=COURI.TTF
-filename.Courier_New_Bold_Italic=COURBI.TTF
-
-filename.Times_New_Roman=TIMES.TTF
-filename.Times_New_Roman_Bold=TIMESBD.TTF
-filename.Times_New_Roman_Italic=TIMESI.TTF
-filename.Times_New_Roman_Bold_Italic=TIMESBI.TTF
-
-filename.SimSun=SIMSUN.TTF
-
-filename.MingLiU=MINGLIU.TTC
-filename.PMingLiU=MINGLIU.TTC
-
-filename.David=DAVID.TTF
-filename.David_Bold=DAVIDBD.TTF
-
-filename.\uff2d\uff33_\u660e\u671d=MSMINCHO.TTC
-filename.\uff2d\uff33_\uff30\u660e\u671d=MSMINCHO.TTC
-filename.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
-filename.\uff2d\uff33_\uff30\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
-
-filename.Gulim=gulim.TTC
-filename.Batang=batang.TTC
-filename.GulimChe=gulim.TTC
-
-filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
-filename.Symbol=SYMBOL.TTF
-filename.Wingdings=WINGDING.TTF
-
--- a/jdk/test/Makefile	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/Makefile	Wed Jul 05 16:50:32 2017 +0200
@@ -1,12 +1,44 @@
 #
-# Makefile to run jtreg
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# 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.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Makefile to run various jdk tests
 #
 
 # Get OS/ARCH specifics
 OSNAME = $(shell uname -s)
+
+# Commands to run on paths to make mixed paths for java on windows
+GETMIXEDPATH=echo
+
+# Location of developer shared files
+SLASH_JAVA = /java
+
+# Platform specific settings
 ifeq ($(OSNAME), SunOS)
   PLATFORM = solaris
-  JCT_PLATFORM = solaris
   ARCH = $(shell uname -p)
   ifeq ($(ARCH), i386)
     ARCH=i586
@@ -14,97 +46,403 @@
 endif
 ifeq ($(OSNAME), Linux)
   PLATFORM = linux
-  JCT_PLATFORM = linux
   ARCH = $(shell uname -m)
   ifeq ($(ARCH), i386)
     ARCH=i586
   endif
 endif
-ifeq ($(OSNAME), Windows_NT)
+
+# Cannot trust uname output
+ifneq ($(PROCESSOR_IDENTIFIER), )
   PLATFORM = windows
-  JCT_PLATFORM = win32
-  ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
-    ARCH=ia64
+  SLASH_JAVA = J:
+  # A variety of ways to say X64 arch :^(
+  PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
+  PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH))
+  PROC_ARCH:=$(subst x64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst intel64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst INTEL64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH))
+  ifeq ($(PROC_ARCH),IA64)
+    ARCH = ia64
   else
-    ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64)
-      ARCH=x64
+    ifeq ($(PROC_ARCH),X64)
+      ARCH = x64
     else
-      ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),EM64T)
-        ARCH=x64
-      else
-        ARCH=i586
-      endif
+      ARCH = i586
     endif
   endif
+  EXESUFFIX = .exe
+  # These need to be different depending on MKS or CYGWIN
+  ifeq ($(findstring cygdrive,$(shell (cd C:/ && pwd))), )
+    GETMIXEDPATH=dosname -s
+  else
+    GETMIXEDPATH=cygpath -m -s
+  endif
 endif
 
+# Utilities used
+CD    = cd
+CP    = cp
+ECHO  = echo
+MKDIR = mkdir
+ZIP   = zip
+
 # Root of this test area (important to use full paths in some places)
 TEST_ROOT := $(shell pwd)
 
-# Default bundle of all test results (passed or not)
-JPRT_ARCHIVE_BUNDLE=$(TEST_ROOT)/JPRT_ARCHIVE_BUNDLE.zip
+# Root of all test results
+ifdef ALT_OUTPUTDIR
+  ABS_OUTPUTDIR = $(ALT_OUTPUTDIR)
+else
+  ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
+endif
+ABS_BUILD_ROOT = $(ABS_OUTPUTDIR)
+ABS_TEST_OUTPUT_DIR := $(ABS_BUILD_ROOT)/testoutput
 
-# Default home for JTREG
-ifeq ($(PLATFORM), windows)
-  JT_HOME = J:/svc/jct-tools3.2.2_02
-  JTREG_KEY_OPTION=-k:!ignore
-else
-  JT_HOME = /java/svc/jct-tools3.2.2_02
-  JTREG_KEY_OPTION=-k:\!ignore
+# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
+ifndef PRODUCT_HOME
+  # Try to use j2sdk-image if it exists
+  ABS_JDK_IMAGE = $(ABS_BUILD_ROOT)/j2sdk-image
+  PRODUCT_HOME :=                       \
+    $(shell                             \
+      if [ -d $(ABS_JDK_IMAGE) ] ; then \
+         $(ECHO) "$(ABS_JDK_IMAGE)";    \
+       else                             \
+         $(ECHO) "$(ABS_BUILD_ROOT)" ;  \
+       fi)
+  PRODUCT_HOME := $(PRODUCT_HOME)
+endif
+
+# Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.)
+#   Should be passed into 'java' only.
+ifdef JPRT_PRODUCT_ARGS
+  JAVA_ARGS = $(JPRT_PRODUCT_ARGS)
 endif
 
-# Default JTREG to run
-JTREG = $(JT_HOME)/$(JCT_PLATFORM)/bin/jtreg
-
-# Default JDK to test
-JAVA_HOME = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
-
-# The test directories to run
-DEFAULT_TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof
-TESTDIRS = $(DEFAULT_TESTDIRS)
+# Expect JPRT to set JPRT_PRODUCT_VM_ARGS (e.g. -Xcomp etc.)
+#   Should be passed into anything running the vm (java, javac, javadoc, ...).
+ifdef JPRT_PRODUCT_VM_ARGS
+  JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
+endif
 
-# Root of all test results
-JTREG_OUTPUT_DIR = $(TEST_ROOT)/o_$(PLATFORM)-$(ARCH)
-
-# Export this setting and pass it in.
-#JAVA_TOOL_OPTIONS = -Djava.awt.headless=true
-#export JAVA_TOOL_OPTIONS
-
-# Default make rule
-all: clean check tests $(JPRT_ARCHIVE_BUNDLE)
-	@echo "Testing completed successfully"
+# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
+ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
+ifdef JPRT_ARCHIVE_BUNDLE
+  ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
+endif
 
-# Chaeck to make sure these directories exist
-check: $(JT_HOME) $(JAVA_HOME) $(JTREG)
+# How to create the test bundle (pass or fail, we want to create this)
+#   Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed.
+ZIP_UP_RESULTS = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)`     \
+	           && $(CD) $(ABS_TEST_OUTPUT_DIR)             \
+	           && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
+BUNDLE_UP_AND_EXIT = ( exitCode=$$? && $(ZIP_UP_RESULTS) && exit $${exitCode} )
+
+################################################################
 
-# Run the tests
-tests: FRC
-	@echo "Using export JAVA_TOOL_OPTIONS=$(JAVA_TOOL_OPTIONS)"
-	@rm -f -r $(JTREG_OUTPUT_DIR)
-	@mkdir -p $(JTREG_OUTPUT_DIR)
-	$(JTREG) -a -v:fail,error \
-          $(JTREG_KEY_OPTION) \
-          -r:$(JTREG_OUTPUT_DIR)/JTreport \
-          -w:$(JTREG_OUTPUT_DIR)/JTwork \
-          -jdk:$(JAVA_HOME) \
-          $(JAVA_TOOL_OPTIONS:%=-vmoption:%) \
-          $(JAVA_ARGS:%=-vmoption:%) \
-          $(TESTDIRS)
+# Default make rule (runs jtreg_tests)
+all: jtreg_tests
+	@$(ECHO) "Testing completed successfully"
 
-# Bundle up the results
-$(JPRT_ARCHIVE_BUNDLE): FRC
-	@rm -f $@
-	@mkdir -p $(@D)
-	( cd $(JTREG_OUTPUT_DIR) && zip -q -r $@ . )
+# Prep for output
+prep: clean
+	@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
+	@$(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)`
 
 # Cleanup
 clean:
-	rm -f -r $(JTREG_OUTPUT_DIR)
-	rm -f $(JPRT_ARCHIVE_BUNDLE)
+	$(RM) -r $(ABS_TEST_OUTPUT_DIR)
+	$(RM) $(ARCHIVE_BUNDLE)
+
+################################################################
+
+# jtreg tests
+
+# Expect JT_HOME to be set for jtreg tests. (home for jtreg)
+JT_HOME = $(SLASH_JAVA)/re/jtreg/4.0/promoted/latest/binaries/jtreg
+ifdef JPRT_JTREG_HOME
+  JT_HOME = $(JPRT_JTREG_HOME)
+endif
+
+# Expect JPRT to set TESTDIRS to the jtreg test dirs
+ifndef TESTDIRS
+  TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof
+endif
+
+# Default JTREG to run (win32 script works for everybody)
+JTREG = $(JT_HOME)/win32/bin/jtreg
+
+jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG)
+	$(RM) $(JTREG).orig
+	cp $(JTREG) $(JTREG).orig
+	$(RM) $(JTREG)
+	sed -e 's@-J\*@-J-*@' $(JTREG).orig > $(JTREG)
+	chmod a+x $(JTREG)
+	( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)");                     \
+          export JT_HOME;                                                    \
+          $(shell $(GETMIXEDPATH) "$(JTREG)")                                \
+            -a -v:fail,error                                                 \
+	    -ignore:quiet                                                    \
+            $(EXTRA_JTREG_OPTIONS)                                           \
+            -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport    \
+            -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork      \
+            -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")                  \
+            $(JAVA_ARGS:%=-javaoptions:%)                                     \
+            $(JAVA_VM_ARGS:%=-vmoption:%)                                    \
+            $(TESTDIRS)                                                      \
+	) ; $(BUNDLE_UP_AND_EXIT)
+
+PHONY_LIST += jtreg_tests
+
+################################################################
+
+# packtest
+
+# Expect JPRT to set JPRT_PACKTEST_HOME.
+PACKTEST_HOME = /net/jprt-web.sfbay.sun.com/jprt/allproducts/packtest
+ifdef JPRT_PACKTEST_HOME
+  PACKTEST_HOME = $(JPRT_PACKTEST_HOME)
+endif
+
+packtest: prep $(PACKTEST_HOME)/ptest $(PRODUCT_HOME)
+	( $(CD) $(PACKTEST_HOME) &&            \
+	    $(PACKTEST_HOME)/ptest             \
+		 -t "$(PRODUCT_HOME)"          \
+	         $(PACKTEST_STRESS_OPTION)     \
+		 $(EXTRA_PACKTEST_OPTIONS)     \
+		 -W $(ABS_TEST_OUTPUT_DIR)     \
+                 $(JAVA_ARGS:%=-J %)           \
+                 $(JAVA_VM_ARGS:%=-J %)        \
+	 ) ; $(BUNDLE_UP_AND_EXIT)
+
+packtest_stress: PACKTEST_STRESS_OPTION=-s
+packtest_stress: packtest
+
+PHONY_LIST += packtest packtest_stress
+
+################################################################
+
+# vmsqe tests
+
+# Expect JPRT to set JPRT_VMSQE_HOME.
+VMSQE_HOME = /java/sqe/comp/vm/testbase/sqe/vm/current/build/latest/vm
+ifdef JPRT_VMSQE_HOME
+  VMSQE_HOME = $(JPRT_VMSQE_HOME)
+endif
+
+# Expect JPRT to set JPRT_RUNVMSQE_HOME.
+RUNVMSQE_HOME = /net/jprt-web.sfbay.sun.com/jprt/allproducts/runvmsqe
+ifdef JPRT_RUNVMSQE_HOME
+  RUNVMSQE_HOME = $(JPRT_RUNVMSQE_HOME)
+endif
+
+# Expect JPRT to set JPRT_TONGA3_HOME.
+TONGA3_HOME = /java/sqe//tools/gtee/harness/tonga
+ifdef JPRT_TONGA3_HOME
+  TONGA3_HOME = $(JPRT_TONGA3_HOME)
+endif
+
+RUNVMSQE_BIN = $(RUNVMSQE_HOME)/bin/runvmsqe
+
+vmsqe_tests: prep $(VMSQE_HOME)/vm $(TONGA3_HOME) $(RUNVMSQE_BIN) $(PRODUCT_HOME)
+	$(RM) -r $(ABS_TEST_OUTPUT_DIR)/vmsqe
+	( $(CD) $(ABS_TEST_OUTPUT_DIR) &&          \
+	    $(RUNVMSQE_BIN)                        \
+		 -jdk "$(PRODUCT_HOME)"            \
+		 -o "$(ABS_TEST_OUTPUT_DIR)/vmsqe" \
+		 -testbase "$(VMSQE_HOME)/vm"      \
+		 -tonga "$(TONGA3_HOME)"           \
+		 -tongajdk "$(ALT_BOOTDIR)"        \
+                 $(JAVA_ARGS)                      \
+                 $(JAVA_VM_ARGS)                   \
+	         $(RUNVMSQE_TEST_OPTION)           \
+		 $(EXTRA_RUNVMSQE_OPTIONS)         \
+	 ) ; $(BUNDLE_UP_AND_EXIT)
+
+vmsqe_jdwp: RUNVMSQE_TEST_OPTION=-jdwp
+vmsqe_jdwp: vmsqe_tests
+
+vmsqe_jdi: RUNVMSQE_TEST_OPTION=-jdi
+vmsqe_jdi: vmsqe_tests
+
+vmsqe_jdb: RUNVMSQE_TEST_OPTION=-jdb
+vmsqe_jdb: vmsqe_tests
+
+vmsqe_quick-jdi: RUNVMSQE_TEST_OPTION=-quick-jdi
+vmsqe_quick-jdi: vmsqe_tests
+
+vmsqe_sajdi: RUNVMSQE_TEST_OPTION=-sajdi
+vmsqe_sajdi: vmsqe_tests
+
+vmsqe_jvmti: RUNVMSQE_TEST_OPTION=-jvmti
+vmsqe_jvmti: vmsqe_tests
+
+vmsqe_hprof: RUNVMSQE_TEST_OPTION=-hprof
+vmsqe_hprof: vmsqe_tests
+
+vmsqe_monitoring: RUNVMSQE_TEST_OPTION=-monitoring
+vmsqe_monitoring: vmsqe_tests
+
+PHONY_LIST += vmsqe_jdwp vmsqe_jdi vmsqe_jdb vmsqe_quick-jdi vmsqe_sajdi \
+              vmsqe_jvmti vmsqe_hprof vmsqe_monitoring vmsqe_tests
+
+################################################################
+
+# jck tests
 
-# Used to force a target rules to run
-FRC:
+JCK_WORK_DIR     = $(ABS_TEST_OUTPUT_DIR)/JCKwork
+JCK_REPORT_DIR   = $(ABS_TEST_OUTPUT_DIR)/JCKreport
+JCK_PROPERTIES   = $(ABS_TEST_OUTPUT_DIR)/jck.properties
+JCK_CONFIG       = $(ABS_TEST_OUTPUT_DIR)/jck.config
+
+JCK_JAVA_EXE     = $(PRODUCT_HOME)/bin/java$(EXESUFFIX)
+
+JCK_JAVATEST_JAR = $(JCK_HOME)/lib/javatest.jar
+JCK_JAVATEST     = $(ALT_BOOTDIR)/bin/java -jar $(JCK_JAVATEST_JAR)
+
+$(JCK_CONFIG): $(TEST_ROOT)/JCK-$(JCK_BUNDLE_NAME)-$(JCK_RELEASE)-base.jti
+	$(RM) $@
+	$(MKDIR) -p $(@D)
+	$(CP) $< $@
+
+$(JCK_PROPERTIES): $(PRODUCT_HOME) $(JCK_JAVA_EXE)
+	$(RM) $@
+	$(MKDIR) -p $(@D)
+	$(ECHO) "jck.env.compiler.compRefExecute.cmdAsFile=$(JCK_JAVA_EXE)" >> $@
+	$(ECHO) "jck.env.compiler.compRefExecute.systemRoot=$(SYSTEMROOT)" >> $@
+	$(ECHO) "jck.env.compiler.testCompile.testCompileAPImultiJVM.cmdAsFile=$(JCK_JAVA_EXE)" >> $@
+	$(ECHO) "jck.tests.tests=$(JCK_BUNDLE_TESTDIRS)" >> $@
+
+jck_tests: prep $(JCK_HOME) $(JCK_PROPERTIES) $(JCK_CONFIG) $(JCK_JAVATEST_JAR)
+	$(MKDIR) -p $(JCK_WORK_DIR)
+	( $(JCK_JAVATEST)                            \
+		-verbose:commands,non-pass           \
+		-testSuite    $(JCK_HOME)            \
+		-workDir      $(JCK_WORK_DIR)        \
+		-config       $(JCK_CONFIG)          \
+		-set -file    $(JCK_PROPERTIES)      \
+		-runtests                            \
+		-writeReport  $(JCK_REPORT_DIR)      \
+        ) ; $(BUNDLE_UP_AND_EXIT)
+
+PHONY_LIST += jck_tests
+
+################################################################
+
+# jck6 tests
+
+JCK6_RELEASE = 6b
+JCK6_DEFAULT_HOME = $(SLASH_JAVA)/re/jck/$(JCK6_RELEASE)/archive/fcs/binaries
+
+# Expect JPRT to set JPRT_JCK6COMPILER_HOME.
+JCK6COMPILER_HOME = $(JCK6_DEFAULT_HOME)/JCK-compiler-$(JCK6_RELEASE)
+ifdef JPRT_JCK6COMPILER_HOME
+  JCK6COMPILER_HOME = $(JPRT_JCK6COMPILER_HOME)
+endif
+
+# Expect JPRT to set JPRT_JCK6RUNTIME_HOME.
+JCK6RUNTIME_HOME = $(JCK6_DEFAULT_HOME)/JCK-runtime-$(JCK6_RELEASE)
+ifdef JPRT_JCK6RUNTIME_HOME
+  JCK6RUNTIME_HOME = $(JPRT_JCK6RUNTIME_HOME)
+endif
+
+# Expect JPRT to set JPRT_JCK6DEVTOOLS_HOME.
+JCK6DEVTOOLS_HOME = $(JCK6_DEFAULT_HOME)/JCK-devtools-$(JCK6_RELEASE)
+ifdef JPRT_JCK6DEVTOOLS_HOME
+  JCK6DEVTOOLS_HOME = $(JPRT_JCK6DEVTOOLS_HOME)
+endif
+
+jck6_tests: JCK_HOME=$(JCK6_HOME)
+jck6_tests: JCK_RELEASE=$(JCK6_RELEASE)
+jck6_tests: jck_tests
+
+jck6compiler: JCK6_HOME=$(JCK6COMPILER_HOME)
+jck6compiler: JCK_BUNDLE_NAME=compiler
+jck6compiler: jck6_tests
+
+jck6compiler_lang: JCK_BUNDLE_TESTDIRS=lang
+jck6compiler_lang: jck6compiler
+
+jck6runtime: JCK6_HOME=$(JCK6RUNTIME_HOME)
+jck6runtime: JCK_BUNDLE_NAME=runtime
+jck6runtime: jck6_tests
+
+jck6runtime_lang: JCK_BUNDLE_TESTDIRS=lang
+jck6runtime_lang: jck6runtime
+
+jck6devtools: JCK6_HOME=$(JCK6DEVTOOLS_HOME)
+jck6devtools: JCK_BUNDLE_NAME=devtools
+jck6devtools: jck6_tests
+
+jck6devtools_lang: JCK_BUNDLE_TESTDIRS=lang
+jck6devtools_lang: jck6devtools
+
+PHONY_LIST += jck6compiler jck6runtime jck6devtools jck6_tests \
+	      jck6compiler_lang jck6runtime_lang jck6devtools_lang
+
+################################################################
+
+# jck7 tests
+
+JCK7_RELEASE = 7
+JCK7_DEFAULT_HOME = $(SLASH_JAVA)/re/jck/$(JCK7_RELEASE)/archive/fcs/binaries
+
+# Expect JPRT to set JPRT_JCK7COMPILER_HOME.
+JCK7COMPILER_HOME = $(JCK7_DEFAULT_HOME)/JCK-compiler-$(JCK7_RELEASE)
+ifdef JPRT_JCK7COMPILER_HOME
+  JCK7COMPILER_HOME = $(JPRT_JCK7COMPILER_HOME)
+endif
+
+# Expect JPRT to set JPRT_JCK7RUNTIME_HOME.
+JCK7RUNTIME_HOME = $(JCK7_DEFAULT_HOME)/JCK-runtime-$(JCK7_RELEASE)
+ifdef JPRT_JCK7RUNTIME_HOME
+  JCK7RUNTIME_HOME = $(JPRT_JCK7RUNTIME_HOME)
+endif
+
+# Expect JPRT to set JPRT_JCK7DEVTOOLS_HOME.
+JCK7DEVTOOLS_HOME = $(JCK7_DEFAULT_HOME)/JCK-devtools-$(JCK7_RELEASE)
+ifdef JPRT_JCK7DEVTOOLS_HOME
+  JCK7DEVTOOLS_HOME = $(JPRT_JCK7DEVTOOLS_HOME)
+endif
+
+jck7_tests: JCK_HOME=$(JCK7_HOME)
+jck7_tests: JCK_RELEASE=$(JCK7_RELEASE)
+jck7_tests: jck_tests
+
+jck7compiler: JCK7_HOME=$(JCK7COMPILER_HOME)
+jck7compiler: JCK_BUNDLE_NAME=compiler
+jck7compiler: jck7_tests
+
+jck7compiler_lang: JCK_BUNDLE_TESTDIRS=lang
+jck7compiler_lang: jck7compiler
+
+jck7runtime: JCK7_HOME=$(JCK7RUNTIME_HOME)
+jck7runtime: JCK_BUNDLE_NAME=runtime
+jck7runtime: jck7_tests
+
+jck7runtime_lang: JCK_BUNDLE_TESTDIRS=lang
+jck7runtime_lang: jck7runtime
+
+jck7devtools: JCK7_HOME=$(JCK7DEVTOOLS_HOME)
+jck7devtools: JCK_BUNDLE_NAME=devtools
+jck7devtools: jck7_tests
+
+jck7devtools_lang: JCK_BUNDLE_TESTDIRS=lang
+jck7devtools_lang: jck7devtools
+
+PHONY_LIST += jck7compiler jck7runtime jck7devtools jck7_tests \
+	      jck7compiler_lang jck7runtime_lang jck7devtools_lang
+
+################################################################
 
 # Phony targets (e.g. these are not filenames)
-.PHONY: all tests clean check
+.PHONY: all clean prep $(PHONY_LIST)
 
+################################################################
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FontClass/FontAccess.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6785424
+ * @summary Test no SecurityException searching for a font.
+ * @run main FontAccess
+ *
+ * This can only test the specific bug if run on something like
+ * Windows Citrix Server where SystemDirectory and WindowsDirectory
+ * are different locations.
+ */
+
+import java.awt.*;
+import java.awt.image.*;
+
+public class FontAccess {
+
+     public static void main(String[] args) {
+        System.setSecurityManager(new SecurityManager());
+        Font f = new Font("Verdana", Font.PLAIN, 12);
+        BufferedImage bi = new BufferedImage(1,1,1);
+        Graphics2D g = bi.createGraphics();
+        g.setFont(f);
+        System.out.println(g.getFontMetrics());
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/GraphicsEnvironment/PreferLocaleFonts.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6752638
+ * @summary Test no NPE calling preferLocaleFonts() on custom GE.
+ * @run main PreferLocaleFonts
+ */
+
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+
+public class PreferLocaleFonts extends GraphicsEnvironment {
+
+    public static void main(String args[]) {
+(new PreferLocaleFonts()).preferLocaleFonts();
+    }
+    public PreferLocaleFonts() {
+        super();
+    }
+    public Graphics2D createGraphics(BufferedImage image) {
+        return null;
+    }
+    public String[] getAvailableFontFamilyNames(Locale locale) {
+        return null;
+    }
+    public String[] getAvailableFontFamilyNames() {
+        return null;
+    }
+    public Font[] getAllFonts() {
+        return null;
+    }
+    public GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
+        return null;
+    }
+    public GraphicsDevice[] getScreenDevices() throws HeadlessException {
+        return null;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/LineBreakMeasurer/FRCTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008-9 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6448405 6519513 6745225
+ * @summary static HashMap cache in LineBreakMeasurer can grow wihout bounds
+ * @run main/othervm/timeout=600 -client -Xms16m -Xmx16m FRCTest
+ */
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.text.*;
+import java.util.Hashtable;
+
+public class FRCTest {
+
+    static AttributedString vanGogh = new AttributedString(
+        "Many people believe that Vincent van Gogh painted his best works " +
+        "during the two-year period he spent in Provence. Here is where he " +
+        "painted The Starry Night--which some consider to be his greatest " +
+        "work of all. However, as his artistic brilliance reached new " +
+        "heights in Provence, his physical and mental health plummeted. ",
+        new Hashtable());
+
+    public static void main(String[] args) {
+
+        // First test the behaviour of Graphics2D.getFontRenderContext();
+        BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g2d = bi.createGraphics();
+        AffineTransform g2dTx = new AffineTransform(2,0,2,0,1,1);
+        g2d.setTransform(g2dTx);
+        AffineTransform frcTx = g2d.getFontRenderContext().getTransform();
+        AffineTransform frcExpected = new AffineTransform(2,0,2,0,0,0);
+        if (!frcTx.equals(frcExpected)) {
+            throw new RuntimeException("FRC Tx may have translate?");
+        }
+
+        // Now test that using different translates with LBM is OK
+        // This test doesn't prove a lot since showing a leak really
+        // requires a basher test that can run for a long time.
+        for (int x=0;x<100;x++) {
+            for (int y=0;y<100;y++) {
+                AttributedCharacterIterator aci = vanGogh.getIterator();
+                AffineTransform tx = AffineTransform.getTranslateInstance(x, y);
+                FontRenderContext frc = new FontRenderContext(tx, false, false);
+                LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
+                lbm.setPosition(aci.getBeginIndex());
+                while (lbm.getPosition() < aci.getEndIndex()) {
+                    lbm.nextLayout(100f);
+                }
+            }
+        }
+
+        for (int x=0;x<25;x++) {
+            for (int y=0;y<25;y++) {
+                AttributedCharacterIterator aci = vanGogh.getIterator();
+                double rot = Math.random()*.4*Math.PI - .2*Math.PI;
+                AffineTransform tx = AffineTransform.getRotateInstance(rot);
+                FontRenderContext frc = new FontRenderContext(tx, false, false);
+                LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
+                lbm.setPosition(aci.getBeginIndex());
+                while (lbm.getPosition() < aci.getEndIndex()) {
+                    lbm.nextLayout(100f);
+                }
+            }
+        }
+    }
+}
--- a/jdk/test/java/io/File/GetXSpace.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/java/io/File/GetXSpace.java	Wed Jul 05 16:50:32 2017 +0200
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 4057701 6286712 6364377
+ * @ignore until 6492634 and 6501010 is fixed
  * @run build GetXSpace
  * @run shell GetXSpace.sh
  * @summary Basic functionality of File.get-X-Space methods.
--- a/jdk/test/java/lang/Thread/StartOOMTest.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/java/lang/Thread/StartOOMTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6379235
+ * @ignore until 6721694 is fixed
  * @run main/othervm -server -Xmx32m -Xms32m -Xss256m StartOOMTest
  * @summary ThreadGroup accounting mistake possible with failure of Thread.start()
  */
--- a/jdk/test/java/lang/reflect/Method/InheritedMethods.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/java/lang/reflect/Method/InheritedMethods.java	Wed Jul 05 16:50:32 2017 +0200
@@ -23,6 +23,7 @@
 
 /* @test
    @bug 4471738
+   @ignore until 6825739 fixed
    @summary Failure to properly traverse class hierarchy in Class.getMethod()
 */
 
--- a/jdk/test/java/util/concurrent/TimeUnit/Basic.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/java/util/concurrent/TimeUnit/Basic.java	Wed Jul 05 16:50:32 2017 +0200
@@ -60,10 +60,11 @@
         equal(1000L, MICROSECONDS.toNanos(1));
 
         long t0 = System.nanoTime();
-        MILLISECONDS.sleep(3);
+        MILLISECONDS.sleep(3); /* See windows bug 6313903, might not sleep */
         long elapsedMillis = (System.nanoTime() - t0)/(1000L * 1000L);
         System.out.printf("elapsed=%d%n", elapsedMillis);
-        check(elapsedMillis >= 3);
+        check(elapsedMillis >= 0);
+        /* Might not sleep on windows: check(elapsedMillis >= 3); */
         check(elapsedMillis < 1000);
 
         //----------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/ClassLoaderLeakTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug     6799583
+ *
+ * @summary Test verifes that LogManager shutdown hook does not cause
+ *          an application classloader leaks.
+ *
+ * @run     main/othervm ClassLoaderLeakTest
+ */
+
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Logger;
+import java.util.logging.Logger;
+
+public class ClassLoaderLeakTest {
+
+    private static CountDownLatch doneSignal;
+    private static CountDownLatch launchSignal;
+    private static ThreadGroup appsThreadGroup;
+    private static Throwable launchFailure = null;
+
+    public static void main(String[] args) {
+        appsThreadGroup = new ThreadGroup("MyAppsThreadGroup");
+        doneSignal = new CountDownLatch(1);
+        launchSignal = new CountDownLatch(1);
+
+        Runnable launcher = new Runnable() {
+            public void run() {
+                try {
+                    ClassLoader cl =
+                        Thread.currentThread().getContextClassLoader();
+                    Class appMain = cl.loadClass("AppTest");
+                    Method launch =
+                        appMain.getDeclaredMethod("launch", doneSignal.getClass());
+
+                    Constructor c = appMain.getConstructor();
+
+                    Object o = c.newInstance();
+
+                    launch.invoke(o, doneSignal);
+
+                } catch (Throwable e) {
+                    launchFailure = e;
+                } finally {
+                    launchSignal.countDown();
+                }
+            }
+        };
+
+        /* prepare test  class loader */
+        URL pwd = null;
+        try {
+
+            pwd = new File(System.getProperty("test.classes",".")).toURL();
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Test failed.", e);
+        }
+        URL[] urls = new URL[] { pwd };
+
+         MyClassLoader appClassLoader = new MyClassLoader(urls, "test0");
+         WeakReference<MyClassLoader> ref =
+                 new WeakReference<MyClassLoader>(appClassLoader);
+
+
+         Thread appThread = new Thread(appsThreadGroup, launcher, "AppThread-0");
+         appThread.setContextClassLoader(appClassLoader);
+
+         appThread.start();
+         appClassLoader = null;
+         launcher = null;
+         appThread = null;
+
+         /* wait for laucnh completion */
+         try {
+             launchSignal.await();
+         } catch (InterruptedException e) {
+         }
+
+         /* check if launch failed */
+         if (launchFailure != null) {
+             throw new RuntimeException("Test failed.", launchFailure);
+         }
+
+         /* wait for test app excution completion */
+         try {
+             doneSignal.await();
+         } catch (InterruptedException e) {
+         }
+
+         /* give a chence to GC */
+         waitAndGC(5);
+
+         if (ref.get() != null) {
+             throw new RuntimeException("Test failed: classloader is still alive");
+         }
+
+         System.out.println("Test passed.");
+    }
+
+    private static class MyClassLoader extends URLClassLoader {
+
+        private static boolean verbose =
+            Boolean.getBoolean("verboseClassLoading");
+        private String uniqClassName;
+
+        public MyClassLoader(URL[] urls, String uniq) {
+            super(urls);
+
+            uniqClassName = uniq;
+        }
+
+        public Class loadClass(String name) throws ClassNotFoundException {
+            if (verbose) {
+                System.out.printf("%s: load class %s\n", uniqClassName, name);
+            }
+            if (uniqClassName.equals(name)) {
+                return Object.class;
+            }
+            return super.loadClass(name);
+        }
+
+        public String toString() {
+            return "MyClassLoader(" + uniqClassName + ")";
+        }
+    }
+
+    private static void waitAndGC(int sec) {
+        int cnt = sec;
+        System.out.print("Wait ");
+        while (cnt-- > 0) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+            // do GC every 3 seconds
+            if (cnt % 3 == 2) {
+                System.gc();
+                System.out.print("+");
+            } else {
+                System.out.print(".");
+            }
+            //checkErrors();
+        }
+        System.out.println("");
+    }
+}
+
+
+class AppTest {
+    public AppTest() {
+
+    }
+
+    public void launch(CountDownLatch done) {
+        Logger log = Logger.getLogger("app_test_logger");
+        log.fine("Test app is launched");
+
+        done.countDown();
+    }
+}
--- a/jdk/test/java/util/logging/LoggingDeadlock2.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/java/util/logging/LoggingDeadlock2.java	Wed Jul 05 16:50:32 2017 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug     6467152
- *
+ * @ignore until 6716076 is fixed
  * @summary deadlock occurs in LogManager initialization and JVM termination
  * @author  Serguei Spitsyn / Hittachi
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/BooleanAttributes.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5082756
+ * @summary ensure that boolean attributes follow ( "TRUE" | "FALSE" )
+ *          including correct (i.e. upper) case
+ *
+ * @run main BooleanAttributes
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.List;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import javax.imageio.stream.MemoryCacheImageOutputStream;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class BooleanAttributes {
+
+    private static TransformerFactory transformerFactory =
+        TransformerFactory.newInstance();
+
+    private static XPath xpathEngine = XPathFactory.newInstance().newXPath();
+
+    public static void main(String[] args) throws Exception {
+        test("image/png", false, "<javax_imageio_1.0 />",
+             "Chroma/BlackIsZero/@value",
+             "Compression/Lossless/@value");
+
+        test("image/png", false,
+             "<javax_imageio_png_1.0>" +
+             "<iTXt><iTXtEntry keyword='Comment' compressionFlag='TRUE' " +
+             "compressionMethod='0' languageTag='en' " +
+             "translatedKeyword='comment' text='foo'/></iTXt>" +
+             "</javax_imageio_png_1.0>",
+             "iTXt/iTXtEntry/@compressionFlag");
+
+        test("image/png", false,
+             "<javax_imageio_png_1.0>" +
+             "<iTXt><iTXtEntry keyword='Comment' compressionFlag='FALSE' " +
+             "compressionMethod='0' languageTag='en' " +
+             "translatedKeyword='comment' text='foo'/></iTXt>" +
+             "</javax_imageio_png_1.0>",
+             "iTXt/iTXtEntry/@compressionFlag");
+
+        test("image/gif", false, "<javax_imageio_1.0 />",
+             "Chroma/BlackIsZero/@value",
+             "Compression/Lossless/@value");
+
+        test("image/gif", false,
+             "<javax_imageio_gif_image_1.0>" +
+             "<ImageDescriptor imageLeftPosition='0' imageTopPosition='0' " +
+             "imageWidth='16' imageHeight='16' interlaceFlag='TRUE' />" +
+             "<LocalColorTable sizeOfLocalColorTable='2' " +
+             "backgroundColorIndex='1' sortFlag='TRUE'>" +
+             "<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
+             "<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
+             "</LocalColorTable>" +
+             "<GraphicControlExtension disposalMethod='doNotDispose' " +
+             "userInputFlag='FALSE' transparentColorFlag='TRUE' " +
+             "delayTime='100' transparentColorIndex='1' />" +
+             "</javax_imageio_gif_image_1.0>",
+             "ImageDescriptor/@interlaceFlag",
+             "LocalColorTable/@sortFlag",
+             "GraphicControlExtension/@userInputFlag",
+             "GraphicControlExtension/@transparentColorFlag");
+
+        test("image/gif", true,
+             "<javax_imageio_gif_stream_1.0>" +
+             "<GlobalColorTable sizeOfGlobalColorTable='2' " +
+             "backgroundColorIndex='1' sortFlag='TRUE'>" +
+             "<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
+             "<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
+             "</GlobalColorTable>" +
+             "</javax_imageio_gif_stream_1.0>",
+             "GlobalColorTable/@sortFlag");
+
+        test("image/jpeg", false, "<javax_imageio_1.0 />",
+             "Compression/Lossless/@value");
+    }
+
+    private static void transform(Source src, Result dst)
+        throws Exception
+    {
+        transformerFactory.newTransformer().transform(src, dst);
+    }
+
+    private static void verify(Node meta, String[] xpaths, boolean required)
+        throws Exception
+    {
+        for (String xpath: xpaths) {
+            NodeList list = (NodeList)
+                xpathEngine.evaluate(xpath, meta, XPathConstants.NODESET);
+            if (list.getLength() == 0 && required)
+                throw new AssertionError("Missing value: " + xpath);
+            for (int i = 0; i < list.getLength(); ++i) {
+                String value = list.item(i).getNodeValue();
+                if (!(value.equals("TRUE") || value.equals("FALSE")))
+                    throw new AssertionError(xpath + " has value " + value);
+            }
+        }
+    }
+
+    public static void test(String mimeType, boolean useStreamMeta,
+                            String metaXml, String... boolXpaths)
+        throws Exception
+    {
+        BufferedImage img =
+            new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+        ImageWriter iw = ImageIO.getImageWritersByMIMEType(mimeType).next();
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        ImageOutputStream ios = new MemoryCacheImageOutputStream(os);
+        iw.setOutput(ios);
+        ImageWriteParam param = null;
+        IIOMetadata streamMeta = iw.getDefaultStreamMetadata(param);
+        IIOMetadata imageMeta =
+            iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), param);
+        IIOMetadata meta = useStreamMeta ? streamMeta : imageMeta;
+        Source src = new StreamSource(new StringReader(metaXml));
+        DOMResult dst = new DOMResult();
+        transform(src, dst);
+        Document doc = (Document)dst.getNode();
+        Element node = doc.getDocumentElement();
+        String metaFormat = node.getNodeName();
+
+        // Verify that the default metadata gets formatted correctly.
+        verify(meta.getAsTree(metaFormat), boolXpaths, false);
+
+        meta.mergeTree(metaFormat, node);
+
+        // Verify that the merged metadata gets formatte correctly.
+        verify(meta.getAsTree(metaFormat), boolXpaths, true);
+
+        iw.write(streamMeta, new IIOImage(img, null, imageMeta), param);
+        iw.dispose();
+        ios.close();
+        ImageReader ir = ImageIO.getImageReader(iw);
+        byte[] bytes = os.toByteArray();
+        if (bytes.length == 0)
+            throw new AssertionError("Zero length image file");
+        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+        ImageInputStream iis = new MemoryCacheImageInputStream(is);
+        ir.setInput(iis);
+        if (useStreamMeta) meta = ir.getStreamMetadata();
+        else meta = ir.getImageMetadata(0);
+
+        // Verify again after writing and re-reading the image
+        verify(meta.getAsTree(metaFormat), boolXpaths, true);
+    }
+
+    public static void xtest(Object... eatAnyArguments) {
+        System.err.println("Disabled test! Change xtest back into test!");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/gif/EncodeSubImageTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug     6795544
+ *
+ * @summary Test verifes that Image I/O gif writer correctly handles
+ *          buffered images based on translated reasters (typically
+ *          produced by getSubImage() method).
+ *
+ * @run     main EncodeSubImageTest gif
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+
+public class EncodeSubImageTest {
+    private static String format = "gif";
+    private static ImageWriter writer;
+    private static String file_suffix;
+    private static final int subSampleX = 2;
+    private static final int subSampleY = 2;
+
+    public static void main(String[] args) throws IOException {
+        if (args.length > 0) {
+            format = args[0];
+        }
+
+        writer = ImageIO.getImageWritersByFormatName(format).next();
+
+        file_suffix =writer.getOriginatingProvider().getFileSuffixes()[0];
+
+        BufferedImage src = createTestImage();
+        EncodeSubImageTest m1 = new EncodeSubImageTest(src);
+        m1.doTest("test_src");
+
+        BufferedImage sub = src.getSubimage(subImageOffset, subImageOffset,
+                src.getWidth() - 2 * subImageOffset,
+                src.getHeight() - 2 * subImageOffset);
+        EncodeSubImageTest m2 = new EncodeSubImageTest(sub);
+        m2.doTest("test_sub");
+    }
+
+    BufferedImage img;
+
+    public EncodeSubImageTest(BufferedImage img) {
+        this.img = img;
+    }
+
+    public void doTest(String prefix) throws IOException {
+        System.out.println(prefix);
+        File f = new File(prefix + file_suffix);
+        write(f, false);
+        verify(f, false);
+
+        System.out.println(prefix + "_subsampled");
+        f = new File(prefix + "_subsampled");
+        write(f, true);
+        verify(f, true);
+
+        System.out.println(prefix + ": Test PASSED.");
+    }
+
+    private static final int subImageOffset = 10;
+
+    private void verify(File f, boolean isSubsampled) {
+        BufferedImage dst = null;
+        try {
+            dst = ImageIO.read(f);
+        } catch (IOException e) {
+            throw new RuntimeException("Test FAILED: can't readin test image " +
+                f.getAbsolutePath(), e);
+        }
+        if (dst == null) {
+            throw new RuntimeException("Test FAILED: no dst image available.");
+        }
+
+        checkPixel(dst, 0, 0, isSubsampled);
+
+        checkPixel(dst, img.getWidth() / 2, img.getHeight() / 2, isSubsampled);
+    }
+
+    private void checkPixel(BufferedImage dst, int x, int y,
+                            boolean isSubsampled)
+    {
+        int dx = isSubsampled ? x / subSampleX : x;
+        int dy = isSubsampled ? y / subSampleY : y;
+        int src_rgb = img.getRGB(x, y);
+        System.out.printf("src_rgb: %x\n", src_rgb);
+
+        int dst_rgb = dst.getRGB(dx, dy);
+        System.out.printf("dst_rgb: %x\n", dst_rgb);
+
+        if (src_rgb != dst_rgb) {
+            throw new RuntimeException("Test FAILED: invalid color in dst");
+        }
+    }
+
+    private static BufferedImage createTestImage() {
+        int w = 100;
+        int h = 100;
+
+        BufferedImage src = new BufferedImage(w, h,
+                BufferedImage.TYPE_BYTE_INDEXED);
+        Graphics g = src.createGraphics();
+        g.setColor(Color.red);
+        g.fillRect(0, 0, w, h);
+        g.setColor(Color.green);
+        g.fillRect(subImageOffset, subImageOffset,
+                w - 2 * subImageOffset, h - 2* subImageOffset);
+        g.setColor(Color.blue);
+        g.fillRect(2 * subImageOffset, 2 * subImageOffset,
+                w - 4 * subImageOffset, h - 4 * subImageOffset);
+        g.dispose();
+
+        return src;
+    }
+
+    private void write(File f, boolean subsample) throws IOException {
+        ImageOutputStream ios = ImageIO.createImageOutputStream(f);
+
+        writer.setOutput(ios);
+        ImageWriteParam p = writer.getDefaultWriteParam();
+        if (subsample) {
+            p.setSourceSubsampling(subSampleX, subSampleY, 0, 0);
+        }
+        writer.write(null, new IIOImage(img, null, null), p);
+        ios.close();
+        writer.reset();
+    }
+}
--- a/jdk/test/javax/imageio/plugins/png/ITXtTest.java	Thu Apr 02 16:51:48 2009 -0700
+++ b/jdk/test/javax/imageio/plugins/png/ITXtTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -123,7 +123,7 @@
         }
         t.keyword = e.getAttribute("keyword");
         t.isCompressed =
-            (Integer.valueOf(e.getAttribute("compressionFlag")).intValue() == 1);
+            Boolean.valueOf(e.getAttribute("compressionFlag")).booleanValue();
         t.compression =
             Integer.valueOf(e.getAttribute("compressionMethod")).intValue();
         t.language = e.getAttribute("languageTag");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/png/ItxtUtf8Test.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6541476 6782079
+ * @summary Write and read a PNG file including an non-latin1 iTXt chunk
+ *          Test also verifies that trunkated png images does not cause
+ *          an OoutOfMemory error.
+ *
+ * @run main ItxtUtf8Test
+ *
+ * @run main/othervm/timeout=10 -Xmx2m ItxtUtf8Test truncate
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
+import javax.imageio.IIOException;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import javax.imageio.stream.MemoryCacheImageOutputStream;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+
+public class ItxtUtf8Test {
+
+    public static final String
+    TEXT = "\u24c9\u24d4\u24e7\u24e3" +
+      "\ud835\udc13\ud835\udc1e\ud835\udc31\ud835\udc2d" +
+      "\u24c9\u24d4\u24e7\u24e3", // a repetition for compression
+    VERBATIM = "\u24e5\u24d4\u24e1\u24d1\u24d0\u24e3\u24d8\u24dc",
+    COMPRESSED = "\u24d2\u24de\u24dc\u24df\u24e1\u24d4\u24e2\u24e2\u24d4\u24d3";
+
+    public static final byte[]
+    VBYTES = {
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x56, // chunk length
+        (byte)0x69, (byte)0x54, (byte)0x58, (byte)0x74, // chunk type "iTXt"
+        (byte)0x76, (byte)0x65, (byte)0x72, (byte)0x62,
+        (byte)0x61, (byte)0x74, (byte)0x69, (byte)0x6d, // keyword "verbatim"
+        (byte)0x00, // separator terminating keyword
+        (byte)0x00, // compression flag
+        (byte)0x00, // compression method, must be zero
+        (byte)0x78, (byte)0x2d, (byte)0x63, (byte)0x69,
+        (byte)0x72, (byte)0x63, (byte)0x6c, (byte)0x65,
+        (byte)0x64, // language tag "x-circled"
+        (byte)0x00, // separator terminating language tag
+        (byte)0xe2, (byte)0x93, (byte)0xa5, // '\u24e5'
+        (byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
+        (byte)0xe2, (byte)0x93, (byte)0xa1, // '\u24e1'
+        (byte)0xe2, (byte)0x93, (byte)0x91, // '\u24d1'
+        (byte)0xe2, (byte)0x93, (byte)0x90, // '\u24d0'
+        (byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
+        (byte)0xe2, (byte)0x93, (byte)0x98, // '\u24d8'
+        (byte)0xe2, (byte)0x93, (byte)0x9c, // '\u24dc'
+        (byte)0x00, // separator terminating the translated keyword
+        (byte)0xe2, (byte)0x93, (byte)0x89, // '\u24c9'
+        (byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
+        (byte)0xe2, (byte)0x93, (byte)0xa7, // '\u24e7'
+        (byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
+        (byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0x93, // '\ud835\udc13'
+        (byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0x9e, // '\ud835\udc1e'
+        (byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0xb1, // '\ud835\udc31'
+        (byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0xad, // '\ud835\udc2d'
+        (byte)0xe2, (byte)0x93, (byte)0x89, // '\u24c9'
+        (byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
+        (byte)0xe2, (byte)0x93, (byte)0xa7, // '\u24e7'
+        (byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
+        (byte)0xb5, (byte)0xcc, (byte)0x97, (byte)0x56 // CRC
+    },
+    CBYTES = {
+        // we don't want to check the chunk length,
+        // as this might depend on implementation.
+        (byte)0x69, (byte)0x54, (byte)0x58, (byte)0x74, // chunk type "iTXt"
+        (byte)0x63, (byte)0x6f, (byte)0x6d, (byte)0x70,
+        (byte)0x72, (byte)0x65, (byte)0x73, (byte)0x73,
+        (byte)0x65, (byte)0x64, // keyword "compressed"
+        (byte)0x00, // separator terminating keyword
+        (byte)0x01, // compression flag
+        (byte)0x00, // compression method, 0=deflate
+        (byte)0x78, (byte)0x2d, (byte)0x63, (byte)0x69,
+        (byte)0x72, (byte)0x63, (byte)0x6c, (byte)0x65,
+        (byte)0x64, // language tag "x-circled"
+        (byte)0x00, // separator terminating language tag
+        // we don't want to check the actual compressed data,
+        // as this might depend on implementation.
+    };
+/*
+*/
+
+    public static void main(String[] args) throws Exception {
+        List argList = Arrays.asList(args);
+        if (argList.contains("truncate")) {
+            try {
+                runTest(false, true);
+                throw new AssertionError("Expect an error for truncated file");
+            }
+            catch (IIOException e) {
+                // expected an error for a truncated image file.
+            }
+        }
+        else {
+            runTest(argList.contains("dump"), false);
+        }
+    }
+
+    public static void runTest(boolean dump, boolean truncate)
+        throws Exception
+    {
+        String format = "javax_imageio_png_1.0";
+        BufferedImage img =
+            new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+        ImageWriter iw = ImageIO.getImageWritersByMIMEType("image/png").next();
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        ImageOutputStream ios = new MemoryCacheImageOutputStream(os);
+        iw.setOutput(ios);
+        IIOMetadata meta =
+            iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), null);
+        DOMImplementationRegistry registry;
+        registry = DOMImplementationRegistry.newInstance();
+        DOMImplementation impl = registry.getDOMImplementation("XML 3.0");
+        Document doc = impl.createDocument(null, format, null);
+        Element root, itxt, entry;
+        root = doc.getDocumentElement();
+        root.appendChild(itxt = doc.createElement("iTXt"));
+        itxt.appendChild(entry = doc.createElement("iTXtEntry"));
+        entry.setAttribute("keyword", "verbatim");
+        entry.setAttribute("compressionFlag", "false");
+        entry.setAttribute("compressionMethod", "0");
+        entry.setAttribute("languageTag", "x-circled");
+        entry.setAttribute("translatedKeyword", VERBATIM);
+        entry.setAttribute("text", TEXT);
+        itxt.appendChild(entry = doc.createElement("iTXtEntry"));
+        entry.setAttribute("keyword", "compressed");
+        entry.setAttribute("compressionFlag", "true");
+        entry.setAttribute("compressionMethod", "0");
+        entry.setAttribute("languageTag", "x-circled");
+        entry.setAttribute("translatedKeyword", COMPRESSED);
+        entry.setAttribute("text", TEXT);
+        meta.mergeTree(format, root);
+        iw.write(new IIOImage(img, null, meta));
+        iw.dispose();
+
+        byte[] bytes = os.toByteArray();
+        if (dump)
+            System.out.write(bytes);
+        if (findBytes(VBYTES, bytes) < 0)
+            throw new AssertionError("verbatim block not found");
+        if (findBytes(CBYTES, bytes) < 0)
+            throw new AssertionError("compressed block not found");
+        int length = bytes.length;
+        if (truncate)
+            length = findBytes(VBYTES, bytes) + 32;
+
+        ImageReader ir = ImageIO.getImageReader(iw);
+        ByteArrayInputStream is = new ByteArrayInputStream(bytes, 0, length);
+        ImageInputStream iis = new MemoryCacheImageInputStream(is);
+        ir.setInput(iis);
+        meta = ir.getImageMetadata(0);
+        Node node = meta.getAsTree(format);
+        for (node = node.getFirstChild();
+             !"iTXt".equals(node.getNodeName());
+             node = node.getNextSibling());
+        boolean verbatimSeen = false, compressedSeen = false;
+        for (node = node.getFirstChild();
+             node != null;
+             node = node.getNextSibling()) {
+            entry = (Element)node;
+            String keyword = entry.getAttribute("keyword");
+            String translatedKeyword = entry.getAttribute("translatedKeyword");
+            String text = entry.getAttribute("text");
+            if ("verbatim".equals(keyword)) {
+                if (verbatimSeen) throw new AssertionError("Duplicate");
+                verbatimSeen = true;
+                if (!VERBATIM.equals(translatedKeyword))
+                    throw new AssertionError("Wrong translated keyword");
+                if (!TEXT.equals(text))
+                    throw new AssertionError("Wrong text");
+            }
+            else if ("compressed".equals(keyword)) {
+                if (compressedSeen) throw new AssertionError("Duplicate");
+                compressedSeen = true;
+                if (!COMPRESSED.equals(translatedKeyword))
+                    throw new AssertionError("Wrong translated keyword");
+                if (!TEXT.equals(text))
+                    throw new AssertionError("Wrong text");
+            }
+            else {
+                throw new AssertionError("Unexpected keyword");
+            }
+        }
+        if (!(verbatimSeen && compressedSeen))
+            throw new AssertionError("Missing chunk");
+    }
+
+    private static final int findBytes(byte[] needle, byte[] haystack) {
+        HAYSTACK: for (int h = 0; h <= haystack.length - needle.length; ++h) {
+            for (int n = 0; n < needle.length; ++n) {
+                if (needle[n] != haystack[h + n]) {
+                    continue HAYSTACK;
+                }
+            }
+            return h;
+        }
+        return -1;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/png/MergeStdCommentTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5106550
+ * @summary Merge a comment using the standard metdata format
+ *          and only a minimal set of attributes
+ */
+
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+
+public class MergeStdCommentTest {
+
+    public static void main(String[] args) throws Exception {
+        String format = "javax_imageio_1.0";
+        BufferedImage img =
+            new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+        ImageWriter iw = ImageIO.getImageWritersByMIMEType("image/png").next();
+        IIOMetadata meta =
+            iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), null);
+        DOMImplementationRegistry registry;
+        registry = DOMImplementationRegistry.newInstance();
+        DOMImplementation impl = registry.getDOMImplementation("XML 3.0");
+        Document doc = impl.createDocument(null, format, null);
+        Element root, text, entry;
+        root = doc.getDocumentElement();
+        root.appendChild(text = doc.createElement("Text"));
+        text.appendChild(entry = doc.createElement("TextEntry"));
+        // keyword isn't #REQUIRED by the standard metadata format.
+        // However, it is required by the PNG format, so we include it here.
+        entry.setAttribute("keyword", "Comment");
+        entry.setAttribute("value", "Some demo comment");
+        meta.mergeTree(format, root);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/stream/StreamCloserLeak/run_test.sh	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,205 @@
+#!/bin/ksh -p
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+#   @test
+#   @bug        6788096
+#   @summary    Test simulates the case of multiple applets executed in
+#               the same VM and verifies that ImageIO shutdown hook
+#               StreamCloser does not cause a leak of classloaders.
+#
+#   @build      test.Main
+#   @build      testapp.Main
+#   @run shell  run_test.sh
+
+# There are several resources which need to be present before many
+#  shell scripts can run.  Following are examples of how to check for
+#  many common ones.
+#
+# Note that the shell used is the Korn Shell, KSH
+#
+# Also note, it is recommended that make files NOT be used.  Rather,
+#  put the individual commands directly into this file.  That way,
+#  it is possible to use command line arguments and other shell tech-
+#  niques to find the compiler, etc on different systems.  For example,
+#  a different path could be used depending on whether this were a
+#  Solaris or Win32 machine, which is more difficult (if even possible)
+#  in a make file.
+
+
+# Beginning of subroutines:
+status=1
+
+#Call this from anywhere to fail the test with an error message
+# usage: fail "reason why the test failed"
+fail()
+ { echo "The test failed :-("
+   echo "$*" 1>&2
+   echo "exit status was $status"
+   exit $status
+ } #end of fail()
+
+#Call this from anywhere to pass the test with a message
+# usage: pass "reason why the test passed if applicable"
+pass()
+ { echo "The test passed!!!"
+   echo "$*" 1>&2
+   exit 0
+ } #end of pass()
+
+# end of subroutines
+
+
+# The beginning of the script proper
+
+# Checking for proper OS
+OS=`uname -s`
+case "$OS" in
+   SunOS )
+      VAR="One value for Sun"
+      DEFAULT_JDK=/usr/local/java/jdk1.2/solaris
+      FILESEP="/"
+      PATHSEP=":"
+      TMP="/tmp"
+      ;;
+
+   Linux )
+      VAR="A different value for Linux"
+      DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386
+      FILESEP="/"
+      PATHSEP=":"
+      TMP="/tmp"
+      ;;
+
+   Windows_95 | Windows_98 | Windows_NT | Windows_ME )
+      VAR="A different value for Win32"
+      DEFAULT_JDK=/usr/local/java/jdk1.2/win32
+      FILESEP="\\"
+      PATHSEP=";"
+      TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}`
+      ;;
+
+   # catch all other OSs
+   * )
+      echo "Unrecognized system!  $OS"
+      fail "Unrecognized system!  $OS"
+      ;;
+esac
+
+# Want this test to run standalone as well as in the harness, so do the
+#  following to copy the test's directory into the harness's scratch directory
+#  and set all appropriate variables:
+
+if [ -z "${TESTJAVA}" ] ; then
+   # TESTJAVA is not set, so the test is running stand-alone.
+   # TESTJAVA holds the path to the root directory of the build of the JDK
+   # to be tested.  That is, any java files run explicitly in this shell
+   # should use TESTJAVA in the path to the java interpreter.
+   # So, we'll set this to the JDK spec'd on the command line.  If none
+   # is given on the command line, tell the user that and use a cheesy
+   # default.
+   # THIS IS THE JDK BEING TESTED.
+   if [ -n "$1" ] ;
+      then TESTJAVA=$1
+      else echo "no JDK specified on command line so using default!"
+	 TESTJAVA=$DEFAULT_JDK
+   fi
+   TESTSRC=.
+   TESTCLASSES=.
+   STANDALONE=1;
+fi
+echo "JDK under test is: $TESTJAVA"
+
+
+###############  YOUR TEST CODE HERE!!!!!!!  #############
+
+#All files required for the test should be in the same directory with
+# this file.  If converting a standalone test to run with the harness,
+# as long as all files are in the same directory and it returns 0 for
+# pass, you should be able to cut and paste it into here and it will
+# run with the test harness.
+
+# This is an example of running something -- test
+# The stuff below catches the exit status of test then passes or fails
+# this shell test as appropriate ( 0 status is considered a pass here )
+
+echo "Create TestApp.jar..."
+
+if [ -f TestApp.jar ] ; then
+    rm -f TestApp.jar
+fi
+
+${TESTJAVA}/bin/jar -cvf TestApp.jar -C ${TESTCLASSES} testapp
+
+if [ $? -ne "0" ] ; then
+    fail "Failed to create TestApp.jar"
+fi
+
+echo "Create Test.jar..."
+if [ -f Test.jar ] ; then
+    rm -f Test.jar
+fi
+
+${TESTJAVA}/bin/jar -cvf Test.jar -C ${TESTCLASSES} test
+
+if [ $? -ne 0 ] ; then
+    fail "Failed to create Test.jar"
+fi
+
+# Prepare temp dir for cahce files
+mkdir ./tmp
+if [ $? -ne 0 ] ; then
+    fail "Unable to create temp directory."
+fi
+
+# Verify that all classoladers are destroyed
+${TESTJAVA}/bin/java -cp Test.jar test.Main
+if [ $? -ne 0 ] ; then
+    fail "Test FAILED: some classloaders weren't destroyed."
+fi
+
+
+# Verify that ImageIO shutdown hook works correcly
+${TESTJAVA}/bin/java -cp Test.jar -DforgetSomeStreams=true test.Main
+if [ $? -ne 0 ] ; then
+    fail "Test FAILED: some classloaders weren't destroyed of shutdown hook failed."
+fi
+
+# sanity check: verify that all cache files were deleted
+cache_files=`ls tmp`
+
+if [ "x${cache_files}" != "x" ] ; then
+    echo "WARNING: some cache files was not deleted: ${cache_files}"
+fi
+
+echo "Test done."
+
+status=$?
+
+if [ $status -eq "0" ] ; then
+    pass ""
+else
+    fail "Test failed due to test plugin was not found."
+fi
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/stream/StreamCloserLeak/test/Main.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package test;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import javax.imageio.stream.ImageInputStream;
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
+public class Main {
+
+    private static ThreadGroup appsThreadGroup;
+
+    private static WeakHashMap<MyClassLoader, String> refs =
+            new WeakHashMap<MyClassLoader, String>();
+
+    /** Collection to simulate forgrotten streams **/
+    private static HashMap<String, ImageInputStream> strongRefs =
+            new HashMap<String, ImageInputStream>();
+
+    private static ConcurrentLinkedQueue<Throwable> problems =
+            new ConcurrentLinkedQueue<Throwable>();
+
+    private static AppContext mainAppContext = null;
+
+    private static CountDownLatch doneSignal;
+
+    private static final int gcTimeout =
+        Integer.getInteger("gcTimeout", 10).intValue();
+
+    private static boolean forgetSomeStreams =
+            Boolean.getBoolean("forgetSomeStreams");
+
+    public static void main(String[] args) throws IOException {
+        mainAppContext = SunToolkit.createNewAppContext();
+        System.out.println("Current context class loader: " +
+                Thread.currentThread().getContextClassLoader());
+
+        appsThreadGroup = new ThreadGroup("MyAppsThreadGroup");
+
+        File jar = new File("TestApp.jar");
+        if (!jar.exists()) {
+            System.out.println(jar.getAbsolutePath() + " was not found!\n" +
+                    "Please install the jar with test application correctly!");
+            throw new RuntimeException("Test failed: no TestApp.jar");
+        }
+
+        URL[] urls = new URL[]{jar.toURL()};
+
+        int numApps = Integer.getInteger("numApps", 20).intValue();
+
+        doneSignal = new CountDownLatch(numApps);
+        int cnt = 0;
+        while (cnt++ < numApps) {
+            launch(urls, "testapp.Main", "launch");
+
+            checkErrors();
+        }
+
+        System.out.println("Wait for apps completion....");
+
+        try {
+            doneSignal.await();
+        } catch (InterruptedException e) {
+        }
+
+        System.out.println("All apps finished.");
+
+        System.gc();
+
+        System.out.flush();
+
+        System.out.println("Enumerate strong refs:");
+        for (String is : strongRefs.keySet()) {
+            System.out.println("-> " + is);
+        }
+
+        System.out.println("=======================");
+
+        // wait few seconds
+        waitAndGC(gcTimeout);
+
+        doneSignal = new CountDownLatch(1);
+
+        Runnable workaround = new Runnable() {
+
+            public void run() {
+                AppContext ctx = null;
+                try {
+                    ctx = SunToolkit.createNewAppContext();
+                } catch (Throwable e) {
+                    // ignore...
+                } finally {
+                    doneSignal.countDown();
+                }
+            }
+        };
+
+        Thread wt = new Thread(appsThreadGroup, workaround, "Workaround");
+        wt.setContextClassLoader(new MyClassLoader(urls, "workaround"));
+        wt.start();
+        wt = null;
+        workaround = null;
+
+        System.out.println("Wait for workaround completion...");
+
+        try {
+            doneSignal.await();
+        } catch (InterruptedException e) {
+        }
+
+        // give a chance to GC
+        waitAndGC(gcTimeout);
+
+        if (!refs.isEmpty()) {
+            System.out.println("Classloaders still alive:");
+
+            for (MyClassLoader l : refs.keySet()) {
+                String val = refs.get(l);
+
+                if (val == null) {
+                    throw new RuntimeException("Test FAILED: Invalid classloader name");
+                }
+                System.out.println("->" + val + (strongRefs.get(val) != null ?
+                                    " (has strong ref)" : ""));
+                if (strongRefs.get(val) == null) {
+                    throw new RuntimeException("Test FAILED: exta class loader is detected! ");
+                }
+            }
+        } else {
+            System.out.println("No alive class loaders!!");
+        }
+        System.out.println("Test PASSED.");
+    }
+
+    private static void waitAndGC(int sec) {
+        int cnt = sec;
+        System.out.print("Wait ");
+        while (cnt-- > 0) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+            // do GC every 3 seconds
+            if (cnt % 3 == 2) {
+                System.gc();
+                System.out.print("+");
+            } else {
+                System.out.print(".");
+            }
+            checkErrors();
+        }
+        System.out.println("");
+    }
+
+    private static void checkErrors() {
+        while (!problems.isEmpty()) {
+            Throwable theProblem = problems.poll();
+            System.out.println("Test FAILED!");
+            do {
+                theProblem.printStackTrace(System.out);
+                theProblem = theProblem.getCause();
+            } while (theProblem != null);
+            throw new RuntimeException("Test FAILED");
+        }
+    }
+    static int counter = 0;
+
+    private static void launch(URL[] urls, final String className,
+                               final String methodName)
+    {
+        final String uniqClassName = "testapp/Uniq" + counter;
+        final boolean saveStrongRef = forgetSomeStreams ? (counter % 5 == 4) : false;
+
+        System.out.printf("%s: launch the app\n", uniqClassName);
+        Runnable launchIt = new Runnable() {
+            public void run() {
+                AppContext ctx = SunToolkit.createNewAppContext();
+
+                try {
+                    Class appMain =
+                        ctx.getContextClassLoader().loadClass(className);
+                    Method launch = appMain.getDeclaredMethod(methodName,
+                                strongRefs.getClass());
+
+                    Constructor c = appMain.getConstructor(String.class,
+                                                           problems.getClass());
+
+                    Object o = c.newInstance(uniqClassName, problems);
+
+                    if (saveStrongRef) {
+                        System.out.printf("%s: force strong ref\n",
+                                          uniqClassName);
+                        launch.invoke(o, strongRefs);
+                    } else {
+                        HashMap<String, ImageInputStream> empty = null;
+                        launch.invoke(o, empty);
+                    }
+
+                    ctx = null;
+                } catch (Throwable e) {
+                    problems.add(e);
+                } finally {
+                    doneSignal.countDown();
+                }
+            }
+        };
+
+        MyClassLoader appClassLoader = new MyClassLoader(urls, uniqClassName);
+
+        refs.put(appClassLoader, uniqClassName);
+
+        Thread appThread = new Thread(appsThreadGroup, launchIt,
+                                      "AppThread" + counter++);
+        appThread.setContextClassLoader(appClassLoader);
+
+        appThread.start();
+        launchIt = null;
+        appThread = null;
+        appClassLoader = null;
+    }
+
+    private static class MyClassLoader extends URLClassLoader {
+
+        private static boolean verbose =
+            Boolean.getBoolean("verboseClassLoading");
+        private String uniqClassName;
+
+        public MyClassLoader(URL[] urls, String uniq) {
+            super(urls);
+
+            uniqClassName = uniq;
+        }
+
+        public Class loadClass(String name) throws ClassNotFoundException {
+            if (verbose) {
+                System.out.printf("%s: load class %s\n", uniqClassName, name);
+            }
+            if (uniqClassName.equals(name)) {
+                return Object.class;
+            }
+            return super.loadClass(name);
+        }
+
+        public String toString() {
+            return "MyClassLoader(" + uniqClassName + ")";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/stream/StreamCloserLeak/testapp/Main.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package testapp;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import javax.imageio.stream.FileCacheImageInputStream;
+import javax.imageio.stream.ImageInputStream;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Main o = new Main("testapp.some.class", null);
+        o.launch(null);
+    }
+
+    private final  String uniqClassName;
+    private final ConcurrentLinkedQueue<Throwable> problems;
+
+    public Main(String uniq, ConcurrentLinkedQueue<Throwable> p) {
+        uniqClassName = uniq;
+        problems = p;
+    }
+
+    public void launch(HashMap<String, ImageInputStream> refs) {
+        System.out.printf("%s: current context class loader: %s\n",
+                          uniqClassName,
+                Thread.currentThread().getContextClassLoader());
+        try {
+            byte[] data = new byte[1024];
+            ByteArrayInputStream bais = new ByteArrayInputStream(data);
+            MyImageInputStream iis = new MyImageInputStream(bais,
+                                                            uniqClassName,
+                                                            problems);
+            if (refs != null) {
+                System.out.printf("%s: added to strong store\n",
+                                  uniqClassName);
+                refs.put(uniqClassName, iis);
+            }
+            iis.read();
+            //leave stream open : let's shutdown hook work!
+        } catch (IOException e) {
+            problems.add(e);
+        }
+    }
+
+    private static class MyImageInputStream extends FileCacheImageInputStream {
+        private final String uniqClassName;
+        private ConcurrentLinkedQueue<Throwable> problems;
+        public MyImageInputStream(InputStream is, String uniq,
+                                  ConcurrentLinkedQueue<Throwable> p) throws IOException
+   {
+            super(is, new File("tmp"));
+            uniqClassName = uniq;
+            problems = p;
+        }
+
+        @Override
+        public void close() throws IOException {
+            Test t = new Test();
+            try {
+                t.doTest(uniqClassName);
+            } catch (Throwable e) {
+                problems.add(e);
+            }
+
+            super.close();
+
+            problems = null;
+        }
+    }
+}
+
+class Test {
+    public void doTest(String uniqClassName) throws ClassNotFoundException {
+        System.out.printf("%s: Current thread: %s\n", uniqClassName,
+                          Thread.currentThread());
+
+        ClassLoader thisCL = this.getClass().getClassLoader();
+        Class uniq = thisCL.loadClass(uniqClassName);
+
+        System.out.printf("%s: test is done!\n",uniqClassName);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/awt/image/DrawByteBinary.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug     6800846
+ *
+ * @summary Test verifes that images with short palette are rendered
+ *          withourt artifacts.
+ *
+ * @run     main DrawByteBinary
+ */
+
+
+import java.awt.*;
+import java.awt.color.*;
+import java.awt.image.*;
+import static java.awt.image.BufferedImage.*;
+
+
+public class DrawByteBinary {
+
+    public static void main(String args[]) {
+        int w = 100, h = 30;
+        int x = 10;
+        byte[] arr = {(byte)0xff, (byte)0x0, (byte)0x00};
+
+        IndexColorModel newCM = new IndexColorModel(1, 2, arr, arr, arr);
+        BufferedImage orig = new BufferedImage(w, h, TYPE_BYTE_BINARY, newCM);
+        Graphics2D g2d = orig.createGraphics();
+        g2d.setColor(Color.white);
+        g2d.fillRect(0, 0, w, h);
+        g2d.setColor(Color.black);
+        g2d.drawLine(x, 0, x, h);
+        g2d.dispose();
+
+        IndexColorModel origCM = (IndexColorModel)orig.getColorModel();
+        BufferedImage test = new BufferedImage(w, h, TYPE_BYTE_BINARY,origCM);
+        g2d = test.createGraphics();
+        g2d.drawImage(orig, 0, 0, null);
+        g2d.dispose();
+
+        int y = h / 2;
+
+        // we expect white color outside the line
+        if (test.getRGB(x - 1, y) != 0xffffffff) {
+            throw new RuntimeException("Invalid color outside the line.");
+        }
+
+        // we expect black color on the line
+        if (test.getRGB(x, y) != 0xff000000) {
+            throw new RuntimeException("Invalid color on the line.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6476665 6523403 6733501
+ * @summary Verifies reading and writing profiles and tags of the standard color
+ * spaces
+ * @run main ReadWriteProfileTest
+ */
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.util.*;
+import java.nio.*;
+import java.util.Hashtable;
+
+public class ReadWriteProfileTest implements Runnable {
+    /* Location of the tag sig counter in 4-byte words */
+    final static int TAG_COUNT_OFFSET = 32;
+
+    /* Location of the tag sig table in 4-byte words */
+    final static int TAG_ELEM_OFFSET = 33;
+
+    static byte[][] profiles;
+    static int [][] tagSigs;
+    static Hashtable<Integer,byte[]> [] tags;
+
+    static int [] cspaces = {ColorSpace.CS_sRGB, ColorSpace.CS_PYCC,
+                             ColorSpace.CS_LINEAR_RGB, ColorSpace.CS_CIEXYZ,
+                             ColorSpace.CS_GRAY};
+
+    static String [] csNames = {"sRGB", "PYCC", "LINEAR_RGB", "CIEXYZ", "GRAY"};
+
+    static void getProfileTags(byte [] data, Hashtable tags) {
+        ByteBuffer byteBuf = ByteBuffer.wrap(data);
+        IntBuffer intBuf = byteBuf.asIntBuffer();
+        int tagCount = intBuf.get(TAG_COUNT_OFFSET);
+        intBuf.position(TAG_ELEM_OFFSET);
+        for (int i = 0; i < tagCount; i++) {
+            int tagSig = intBuf.get();
+            int tagDataOff = intBuf.get();
+            int tagSize = intBuf.get();
+
+            byte [] tagData = new byte[tagSize];
+            byteBuf.position(tagDataOff);
+            byteBuf.get(tagData);
+            tags.put(tagSig, tagData);
+        }
+    }
+
+    static {
+        profiles = new byte[cspaces.length][];
+        tags = new Hashtable[cspaces.length];
+
+        for (int i = 0; i < cspaces.length; i++) {
+            ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
+            profiles[i] = pf.getData();
+            tags[i] = new Hashtable();
+            getProfileTags(profiles[i], tags[i]);
+        }
+    }
+
+    public void run() {
+        for (int i = 0; i < cspaces.length; i++) {
+            ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
+            byte [] data = pf.getData();
+            pf = ICC_Profile.getInstance(data);
+            if (!Arrays.equals(data, profiles[i])) {
+                System.err.println("Incorrect result of getData() " + "with " +
+                                   csNames[i] + " profile");
+                throw new RuntimeException("Incorrect result of getData()");
+            }
+
+            for (int tagSig : tags[i].keySet()) {
+                byte [] tagData = pf.getData(tagSig);
+                byte [] empty = new byte[tagData.length];
+                pf.setData(tagSig, empty);
+                pf.setData(tagSig, tagData);
+
+                byte [] tagData1 = pf.getData(tagSig);
+
+                if (!Arrays.equals(tagData1, tags[i].get(tagSig)))
+                {
+                    System.err.println("Incorrect result of getData(int) with" +
+                                       " tag " +
+                                       Integer.toHexString(tagSig) +
+                                       " of " + csNames[i] + " profile");
+
+                    throw new RuntimeException("Incorrect result of " +
+                                               "getData(int)");
+                }
+            }
+        }
+    }
+
+    public static void main(String [] args) {
+        ReadWriteProfileTest test = new ReadWriteProfileTest();
+        test.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/pisces/DashStrokeTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary verify that first element is a dash
+ * @bug 6793344
+ */
+
+import java.awt.*;
+import java.awt.image.*;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class DashStrokeTest extends Component {
+
+    static BufferedImage bi;
+    static boolean printed = false;
+
+    public Dimension getPreferredSize() {
+      return new Dimension(200,200);
+    }
+
+    public static void drawGui() {
+        bi = new BufferedImage(200, 20, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g2d = bi.createGraphics();
+        BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+                BasicStroke.JOIN_ROUND, 1.0f, new float[] { 0.0f, 200 },
+                1.0f);
+
+        g2d.setStroke(dashStroke);
+        g2d.setColor(Color.RED);
+        g2d.drawLine(5,10, 100,10);
+        printed =true;
+    }
+
+    public static void main(String[] args) {
+            try {
+            SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                drawGui();
+            }
+
+            });
+            } catch (Exception e) {
+            }
+
+            if (printed) {
+                checkBI(bi, Color.RED);
+            }
+    }
+
+    static void checkBI(BufferedImage bi, Color badColor) {
+      int badrgb = badColor.getRGB();
+
+      int col = bi.getRGB(6, 9);
+      if (col == badrgb) {
+          throw new RuntimeException("A pixel was turned on. ");
+      }
+   }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/pisces/JoinMiterTest.java	Wed Jul 05 16:50:32 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary Pass if no RuntimeException.
+ * @bug 6812600
+ */
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+public class JoinMiterTest {
+
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200,
+BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+    g.translate(25, 100);
+    g.setPaint(Color.BLACK);
+    g.setStroke(new BasicStroke(20, BasicStroke.CAP_BUTT,
+                                BasicStroke.JOIN_MITER));
+    g.draw(new Polygon(new int[] {0, 150, 0}, new int[] {75, 0, -75}, 3));
+    if (image.getRGB(16, 10) == Color.WHITE.getRGB()) {
+      throw new RuntimeException("Miter is not rendered.");
+    }
+  }
+}