Merge jdk7-b54
authorduke
Wed, 05 Jul 2017 16:50:36 +0200
changeset 2418 15096652c4d4
parent 2417 bd1dce471e2a (diff)
parent 2329 2fc3cf4dfd0d (current diff)
child 2419 c27d5e6924b2
child 2420 0b27fe141322
child 2421 c7888e8ac47a
child 2423 2cf529fea081
child 2477 f6d72be571ab
child 2502 45f0ffd05a04
child 2504 0734512b1faf
child 2506 720827f5391b
child 2508 3270fd3540c9
child 2515 939c60aca851
child 2518 2d8171575a81
child 2525 6f4236920636
child 2542 d859108aea12
child 2676 e22d7be9f23a
child 2694 ab517576696d
Merge
--- a/.hgtags-top-repo	Wed Jul 05 16:50:04 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 16:50:36 2017 +0200
@@ -27,3 +27,4 @@
 5111e13e44e542fe945b47ab154546daec36737d jdk7-b50
 0f0189d55ce4a1f7840da7582ac7d970b3b7ab15 jdk7-b51
 4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52
+c235f4a8559d196879c56af80159f67ee5d0e720 jdk7-b53
--- a/corba/.hgtags	Wed Jul 05 16:50:04 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 16:50:36 2017 +0200
@@ -27,3 +27,4 @@
 0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50
 3eb8f1047a7402a9a79937d1c39560e931e91da2 jdk7-b51
 bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52
+3c4d73194f6f89f040ae3b2d257335dfa8a1b2b5 jdk7-b53
--- a/hotspot/.hgtags	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/make/hotspot_version	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/asm/assembler.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_core	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodKlass.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/oop.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/block.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/chaitin.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/coalesce.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/machnode.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/handles.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/hpi.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/orderAccess.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/orderAccess.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/reflection.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Jul 05 16:50:36 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:36 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:36 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:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 16:50:36 2017 +0200
@@ -27,3 +27,4 @@
 e8514e2be76d90889ebdb90d627aca2db5c150c6 jdk7-b50
 ae890d80d5dffcd4dc77a1f17d768e192d1852c7 jdk7-b51
 69ad87dc25cbcaaaded4727199395ad0c78bc427 jdk7-b52
+e8837366d3fd72f7c7a47ebfdbd5106c16156f12 jdk7-b53
--- a/jaxws/.hgtags	Wed Jul 05 16:50:04 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 16:50:36 2017 +0200
@@ -27,3 +27,4 @@
 5be52db581f1ea91ab6e0eb34ba7f439125bfb16 jdk7-b50
 41a66a42791ba90bff489af72cbfea71be9b40a5 jdk7-b51
 e646890d18b770f625f14ed4ad5c50554d8d3d8b jdk7-b52
+b250218eb2e534384667ec73e3713e684667fd4c jdk7-b53
--- a/jdk/.hgtags	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/common/Defs-linux.gmk	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/common/Defs-solaris.gmk	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/common/Defs-windows.gmk	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/common/shared/Defs-java.gmk	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/java/fdlibm/Makefile	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/jprt.properties	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/sun/awt/Makefile	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/make/sun/xawt/mapfile-vers	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/javax/imageio/ImageTypeSpecifier.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/font/FileFontStrike.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/font/FontManager.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/font/GlyphLayout.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/font/StrikeCache.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/cmm/ProfileActivator.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/awt/image/dither.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/solaris/classes/sun/awt/X11/XFontPeer.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/solaris/classes/sun/font/FcFontConfiguration.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintJob.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WFontConfiguration.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ /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	Wed Jul 05 16:50:04 2017 +0200
+++ /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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/Makefile	Wed Jul 05 16:50:36 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:36 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:36 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:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/java/io/File/GetXSpace.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/java/lang/Thread/StartOOMTest.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/java/lang/reflect/Method/InheritedMethods.java	Wed Jul 05 16:50:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/java/util/concurrent/TimeUnit/Basic.java	Wed Jul 05 16:50:36 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:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/java/util/logging/LoggingDeadlock2.java	Wed Jul 05 16:50:36 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:36 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:36 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	Wed Jul 05 16:50:04 2017 +0200
+++ b/jdk/test/javax/imageio/plugins/png/ITXtTest.java	Wed Jul 05 16:50:36 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:36 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:36 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:36 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:36 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:36 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:36 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:36 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:36 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:36 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.");
+    }
+  }
+}
--- a/langtools/.hgtags	Wed Jul 05 16:50:04 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 16:50:36 2017 +0200
@@ -27,3 +27,4 @@
 46f2f6ed96f13fc49fec3d1b6aa616686128cb57 jdk7-b50
 8c55d5b0ed71ed3a749eb97e4eab79b4831649b8 jdk7-b51
 29329051d483d39f66073752ba4afbf29d893cfe jdk7-b52
+dbdeb4a7581b2a8699644b91cae6793cb01953f7 jdk7-b53