Merge jdk7-b63
authorduke
Wed, 05 Jul 2017 16:55:26 +0200
changeset 3029 dfd8506f74c3
parent 3028 9136c5aa1be9 (diff)
parent 2992 bb2fb2694e79 (current diff)
child 3030 b1e6aabbdfd5
child 3031 0d411f80953c
child 3035 3df38ba3991f
child 3042 4905b291b676
child 3044 6d4ed1445c2c
child 3092 4c616e2ae07b
child 3119 1159db0ff0c5
child 3123 52d43f13a156
child 3127 750c9087d287
child 3132 5b8a9427ecc5
child 3134 9bd8eb50ad5a
child 3136 e62e06dbbcc7
child 3147 cc29a56c82ec
child 3159 f5dc0bb134b4
child 3166 db3342c67a1c
child 3181 9ab470566076
child 3286 c7a960b37b2e
Merge
--- a/.hgtags-top-repo	Wed Jul 05 16:55:03 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 030142474602b4a067662fffc0c8e541de5a78df jdk7-b59
 39565502682c7085369bd09e51640919dc741097 jdk7-b60
 472c21584cfd7e9c0229ad6a100366a5c03d2976 jdk7-b61
+c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62
--- a/corba/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 7e6b2b55c00cc523b468272353ada3979adbbf16 jdk7-b59
 f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60
 e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61
+65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62
--- a/hotspot/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 c55be0c7bd32c016c52218eb4c8b5da8a75450b5 jdk7-b59
 a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60
 27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61
+a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62
--- a/hotspot/make/hotspot_version	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/make/hotspot_version	Wed Jul 05 16:55:26 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=16
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=04
+HS_BUILD_NUMBER=05
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -1157,6 +1157,13 @@
   } else {
     // We're done with marking.
     JavaThread::satb_mark_queue_set().set_active_all_threads(false);
+
+    if (VerifyDuringGC) {
+      g1h->prepare_for_verify();
+      g1h->verify(/* allow_dirty */      true,
+                  /* silent */           false,
+                  /* use_prev_marking */ false);
+    }
   }
 
 #if VERIFY_OBJS_PROCESSED
@@ -1747,12 +1754,12 @@
   // races with it goes around and waits for completeCleanup to finish.
   g1h->increment_total_collections();
 
-#ifndef PRODUCT
   if (VerifyDuringGC) {
-    G1CollectedHeap::heap()->prepare_for_verify();
-    G1CollectedHeap::heap()->verify(true,false);
+    g1h->prepare_for_verify();
+    g1h->verify(/* allow_dirty */      true,
+                /* silent */           false,
+                /* use_prev_marking */ true);
   }
-#endif
 }
 
 void ConcurrentMark::completeCleanup() {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -1535,6 +1535,15 @@
   guarantee(_hrs != NULL, "Couldn't allocate HeapRegionSeq");
   guarantee(_cur_alloc_region == NULL, "from constructor");
 
+  // 6843694 - ensure that the maximum region index can fit
+  // in the remembered set structures.
+  const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
+  guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
+
+  const size_t cards_per_region = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift;
+  size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1;
+  guarantee(cards_per_region < max_cards_per_region, "too many cards per region");
+
   _bot_shared = new G1BlockOffsetSharedArray(_reserved,
                                              heap_word_size(init_byte_size));
 
@@ -2127,17 +2136,22 @@
 };
 
 class VerifyObjsInRegionClosure: public ObjectClosure {
+private:
   G1CollectedHeap* _g1h;
   size_t _live_bytes;
   HeapRegion *_hr;
+  bool _use_prev_marking;
 public:
-  VerifyObjsInRegionClosure(HeapRegion *hr) : _live_bytes(0), _hr(hr) {
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  VerifyObjsInRegionClosure(HeapRegion *hr, bool use_prev_marking)
+    : _live_bytes(0), _hr(hr), _use_prev_marking(use_prev_marking) {
     _g1h = G1CollectedHeap::heap();
   }
   void do_object(oop o) {
     VerifyLivenessOopClosure isLive(_g1h);
     assert(o != NULL, "Huh?");
-    if (!_g1h->is_obj_dead(o)) {
+    if (!_g1h->is_obj_dead_cond(o, _use_prev_marking)) {
       o->oop_iterate(&isLive);
       if (!_hr->obj_allocated_since_prev_marking(o))
         _live_bytes += (o->size() * HeapWordSize);
@@ -2176,17 +2190,22 @@
 };
 
 class VerifyRegionClosure: public HeapRegionClosure {
-public:
+private:
   bool _allow_dirty;
   bool _par;
-  VerifyRegionClosure(bool allow_dirty, bool par = false)
-    : _allow_dirty(allow_dirty), _par(par) {}
+  bool _use_prev_marking;
+public:
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking)
+    : _allow_dirty(allow_dirty), _par(par),
+      _use_prev_marking(use_prev_marking) {}
   bool doHeapRegion(HeapRegion* r) {
     guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue,
               "Should be unclaimed at verify points.");
     if (!r->continuesHumongous()) {
-      VerifyObjsInRegionClosure not_dead_yet_cl(r);
-      r->verify(_allow_dirty);
+      VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking);
+      r->verify(_allow_dirty, _use_prev_marking);
       r->object_iterate(&not_dead_yet_cl);
       guarantee(r->max_live_bytes() >= not_dead_yet_cl.live_bytes(),
                 "More live objects than counted in last complete marking.");
@@ -2199,10 +2218,13 @@
 private:
   G1CollectedHeap* _g1h;
   bool             _failures;
-
+  bool             _use_prev_marking;
 public:
-  VerifyRootsClosure() :
-    _g1h(G1CollectedHeap::heap()), _failures(false) { }
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  VerifyRootsClosure(bool use_prev_marking) :
+    _g1h(G1CollectedHeap::heap()), _failures(false),
+    _use_prev_marking(use_prev_marking) { }
 
   bool failures() { return _failures; }
 
@@ -2213,7 +2235,7 @@
   void do_oop(oop* p) {
     oop obj = *p;
     if (obj != NULL) {
-      if (_g1h->is_obj_dead(obj)) {
+      if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) {
         gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
                                "points to dead obj "PTR_FORMAT, p, (void*) obj);
         obj->print_on(gclog_or_tty);
@@ -2229,24 +2251,35 @@
 private:
   G1CollectedHeap* _g1h;
   bool _allow_dirty;
+  bool _use_prev_marking;
 
 public:
-  G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty) :
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty,
+                  bool use_prev_marking) :
     AbstractGangTask("Parallel verify task"),
-    _g1h(g1h), _allow_dirty(allow_dirty) { }
+    _g1h(g1h), _allow_dirty(allow_dirty),
+    _use_prev_marking(use_prev_marking) { }
 
   void work(int worker_i) {
     HandleMark hm;
-    VerifyRegionClosure blk(_allow_dirty, true);
+    VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking);
     _g1h->heap_region_par_iterate_chunked(&blk, worker_i,
                                           HeapRegion::ParVerifyClaimValue);
   }
 };
 
 void G1CollectedHeap::verify(bool allow_dirty, bool silent) {
+  verify(allow_dirty, silent, /* use_prev_marking */ true);
+}
+
+void G1CollectedHeap::verify(bool allow_dirty,
+                             bool silent,
+                             bool use_prev_marking) {
   if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
     if (!silent) { gclog_or_tty->print("roots "); }
-    VerifyRootsClosure rootsCl;
+    VerifyRootsClosure rootsCl(use_prev_marking);
     process_strong_roots(false,
                          SharedHeap::SO_AllClasses,
                          &rootsCl,
@@ -2257,7 +2290,7 @@
       assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
              "sanity check");
 
-      G1ParVerifyTask task(this, allow_dirty);
+      G1ParVerifyTask task(this, allow_dirty, use_prev_marking);
       int n_workers = workers()->total_workers();
       set_par_threads(n_workers);
       workers()->run_task(&task);
@@ -2271,7 +2304,7 @@
       assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
              "sanity check");
     } else {
-      VerifyRegionClosure blk(allow_dirty);
+      VerifyRegionClosure blk(allow_dirty, false, use_prev_marking);
       _hrs->iterate(&blk);
     }
     if (!silent) gclog_or_tty->print("remset ");
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -59,6 +59,9 @@
 typedef GenericTaskQueue<oop*>    RefToScanQueue;
 typedef GenericTaskQueueSet<oop*> RefToScanQueueSet;
 
+typedef int RegionIdx_t;   // needs to hold [ 0..max_regions() )
+typedef int CardIdx_t;     // needs to hold [ 0..CardsPerRegion )
+
 enum G1GCThreadGroups {
   G1CRGroup = 0,
   G1ZFGroup = 1,
@@ -1046,6 +1049,17 @@
   virtual void prepare_for_verify();
 
   // Perform verification.
+
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  // NOTE: Only the "prev" marking information is guaranteed to be
+  // consistent most of the time, so most calls to this should use
+  // use_prev_marking == true. Currently, there is only one case where
+  // this is called with use_prev_marking == false, which is to verify
+  // the "next" marking information at the end of remark.
+  void verify(bool allow_dirty, bool silent, bool use_prev_marking);
+
+  // Override; it uses the "prev" marking information
   virtual void verify(bool allow_dirty, bool silent);
   virtual void print() const;
   virtual void print_on(outputStream* st) const;
@@ -1122,6 +1136,18 @@
   bool isMarkedPrev(oop obj) const;
   bool isMarkedNext(oop obj) const;
 
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  bool is_obj_dead_cond(const oop obj,
+                        const HeapRegion* hr,
+                        const bool use_prev_marking) const {
+    if (use_prev_marking) {
+      return is_obj_dead(obj, hr);
+    } else {
+      return is_obj_ill(obj, hr);
+    }
+  }
+
   // Determine if an object is dead, given the object and also
   // the region to which the object belongs. An object is dead
   // iff a) it was not allocated since the last mark and b) it
@@ -1159,8 +1185,19 @@
   // Added if it is in permanent gen it isn't dead.
   // Added if it is NULL it isn't dead.
 
-  bool is_obj_dead(oop obj) {
-    HeapRegion* hr = heap_region_containing(obj);
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  bool is_obj_dead_cond(const oop obj,
+                        const bool use_prev_marking) {
+    if (use_prev_marking) {
+      return is_obj_dead(obj);
+    } else {
+      return is_obj_ill(obj);
+    }
+  }
+
+  bool is_obj_dead(const oop obj) {
+    const HeapRegion* hr = heap_region_containing(obj);
     if (hr == NULL) {
       if (Universe::heap()->is_in_permanent(obj))
         return false;
@@ -1170,8 +1207,8 @@
     else return is_obj_dead(obj, hr);
   }
 
-  bool is_obj_ill(oop obj) {
-    HeapRegion* hr = heap_region_containing(obj);
+  bool is_obj_ill(const oop obj) {
+    const HeapRegion* hr = heap_region_containing(obj);
     if (hr == NULL) {
       if (Universe::heap()->is_in_permanent(obj))
         return false;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -40,15 +40,19 @@
 {}
 
 class VerifyLiveClosure: public OopClosure {
+private:
   G1CollectedHeap* _g1h;
   CardTableModRefBS* _bs;
   oop _containing_obj;
   bool _failures;
   int _n_failures;
+  bool _use_prev_marking;
 public:
-  VerifyLiveClosure(G1CollectedHeap* g1h) :
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  VerifyLiveClosure(G1CollectedHeap* g1h, bool use_prev_marking) :
     _g1h(g1h), _bs(NULL), _containing_obj(NULL),
-    _failures(false), _n_failures(0)
+    _failures(false), _n_failures(0), _use_prev_marking(use_prev_marking)
   {
     BarrierSet* bs = _g1h->barrier_set();
     if (bs->is_a(BarrierSet::CardTableModRef))
@@ -68,11 +72,13 @@
 
   void do_oop(oop* p) {
     assert(_containing_obj != NULL, "Precondition");
-    assert(!_g1h->is_obj_dead(_containing_obj), "Precondition");
+    assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking),
+           "Precondition");
     oop obj = *p;
     if (obj != NULL) {
       bool failed = false;
-      if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead(obj)) {
+      if (!_g1h->is_in_closed_subset(obj) ||
+          _g1h->is_obj_dead_cond(obj, _use_prev_marking)) {
         if (!_failures) {
           gclog_or_tty->print_cr("");
           gclog_or_tty->print_cr("----------");
@@ -647,19 +653,23 @@
   G1OffsetTableContigSpace::print_on(st);
 }
 
+void HeapRegion::verify(bool allow_dirty) const {
+  verify(allow_dirty, /* use_prev_marking */ true);
+}
+
 #define OBJ_SAMPLE_INTERVAL 0
 #define BLOCK_SAMPLE_INTERVAL 100
 
 // This really ought to be commoned up into OffsetTableContigSpace somehow.
 // We would need a mechanism to make that code skip dead objects.
 
-void HeapRegion::verify(bool allow_dirty) const {
+void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   HeapWord* p = bottom();
   HeapWord* prev_p = NULL;
   int objs = 0;
   int blocks = 0;
-  VerifyLiveClosure vl_cl(g1);
+  VerifyLiveClosure vl_cl(g1, use_prev_marking);
   while (p < top()) {
     size_t size = oop(p)->size();
     if (blocks == BLOCK_SAMPLE_INTERVAL) {
@@ -671,7 +681,7 @@
     }
     if (objs == OBJ_SAMPLE_INTERVAL) {
       oop obj = oop(p);
-      if (!g1->is_obj_dead(obj, this)) {
+      if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
         obj->verify();
         vl_cl.set_containing_obj(obj);
         obj->oop_iterate(&vl_cl);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -782,7 +782,16 @@
   void print() const;
   void print_on(outputStream* st) const;
 
-  // Override
+  // use_prev_marking == true  -> use "prev" marking information,
+  // use_prev_marking == false -> use "next" marking information
+  // NOTE: Only the "prev" marking information is guaranteed to be
+  // consistent most of the time, so most calls to this should use
+  // use_prev_marking == true. Currently, there is only one case where
+  // this is called with use_prev_marking == false, which is to verify
+  // the "next" marking information at the end of remark.
+  void verify(bool allow_dirty, bool use_prev_marking) const;
+
+  // Override; it uses the "prev" marking information
   virtual void verify(bool allow_dirty) const;
 
 #ifdef DEBUG
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -109,7 +109,7 @@
     return new PerRegionTable(hr);
   }
 
-  void add_card_work(short from_card, bool par) {
+  void add_card_work(CardIdx_t from_card, bool par) {
     if (!_bm.at(from_card)) {
       if (par) {
         if (_bm.par_at_put(from_card, 1)) {
@@ -141,11 +141,11 @@
     // and adding a bit to the new table is never incorrect.
     if (loc_hr->is_in_reserved(from)) {
       size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom());
-      size_t from_card =
-        hw_offset >>
-        (CardTableModRefBS::card_shift - LogHeapWordSize);
+      CardIdx_t from_card = (CardIdx_t)
+          hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize);
 
-      add_card_work((short) from_card, par);
+      assert(0 <= from_card && from_card < CardsPerRegion, "Must be in range.");
+      add_card_work(from_card, par);
     }
   }
 
@@ -190,11 +190,11 @@
 #endif
   }
 
-  void add_card(short from_card_index) {
+  void add_card(CardIdx_t from_card_index) {
     add_card_work(from_card_index, /*parallel*/ true);
   }
 
-  void seq_add_card(short from_card_index) {
+  void seq_add_card(CardIdx_t from_card_index) {
     add_card_work(from_card_index, /*parallel*/ false);
   }
 
@@ -604,7 +604,7 @@
 
   // Note that this may be a continued H region.
   HeapRegion* from_hr = _g1h->heap_region_containing_raw(from);
-  size_t from_hrs_ind = (size_t)from_hr->hrs_index();
+  RegionIdx_t from_hrs_ind = (RegionIdx_t) from_hr->hrs_index();
 
   // If the region is already coarsened, return.
   if (_coarse_map.at(from_hrs_ind)) {
@@ -627,11 +627,11 @@
       uintptr_t from_hr_bot_card_index =
         uintptr_t(from_hr->bottom())
           >> CardTableModRefBS::card_shift;
-      int card_index = from_card - from_hr_bot_card_index;
+      CardIdx_t card_index = from_card - from_hr_bot_card_index;
       assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion,
              "Must be in range.");
       if (G1HRRSUseSparseTable &&
-          _sparse_table.add_card((short) from_hrs_ind, card_index)) {
+          _sparse_table.add_card(from_hrs_ind, card_index)) {
         if (G1RecordHRRSOops) {
           HeapRegionRemSet::record(hr(), from);
 #if HRRS_VERBOSE
@@ -656,9 +656,9 @@
       }
 
       // Otherwise, transfer from sparse to fine-grain.
-      short cards[SparsePRTEntry::CardsPerEntry];
+      CardIdx_t cards[SparsePRTEntry::CardsPerEntry];
       if (G1HRRSUseSparseTable) {
-        bool res = _sparse_table.get_cards((short) from_hrs_ind, &cards[0]);
+        bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]);
         assert(res, "There should have been an entry");
       }
 
@@ -679,13 +679,13 @@
       // Add in the cards from the sparse table.
       if (G1HRRSUseSparseTable) {
         for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) {
-          short c = cards[i];
+          CardIdx_t c = cards[i];
           if (c != SparsePRTEntry::NullEntry) {
             prt->add_card(c);
           }
         }
         // Now we can delete the sparse entry.
-        bool res = _sparse_table.delete_entry((short) from_hrs_ind);
+        bool res = _sparse_table.delete_entry(from_hrs_ind);
         assert(res, "It should have been there.");
       }
     }
@@ -1030,7 +1030,7 @@
 bool OtherRegionsTable::contains_reference_locked(oop* from) const {
   HeapRegion* hr = _g1h->heap_region_containing_raw(from);
   if (hr == NULL) return false;
-  size_t hr_ind = hr->hrs_index();
+  RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index();
   // Is this region in the coarse map?
   if (_coarse_map.at(hr_ind)) return true;
 
@@ -1045,8 +1045,9 @@
     uintptr_t hr_bot_card_index =
       uintptr_t(hr->bottom()) >> CardTableModRefBS::card_shift;
     assert(from_card >= hr_bot_card_index, "Inv");
-    int card_index = from_card - hr_bot_card_index;
-    return _sparse_table.contains_card((short)hr_ind, card_index);
+    CardIdx_t card_index = from_card - hr_bot_card_index;
+    assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, "Must be in range.");
+    return _sparse_table.contains_card(hr_ind, card_index);
   }
 
 
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -33,7 +33,7 @@
     sprt_iter->init(this);
 }
 
-void SparsePRTEntry::init(short region_ind) {
+void SparsePRTEntry::init(RegionIdx_t region_ind) {
   _region_ind = region_ind;
   _next_index = NullEntry;
 #if UNROLL_CARD_LOOPS
@@ -43,11 +43,12 @@
   _cards[2] = NullEntry;
   _cards[3] = NullEntry;
 #else
-  for (int i = 0; i < CardsPerEntry; i++) _cards[i] = NullEntry;
+  for (int i = 0; i < CardsPerEntry; i++)
+    _cards[i] = NullEntry;
 #endif
 }
 
-bool SparsePRTEntry::contains_card(short card_index) const {
+bool SparsePRTEntry::contains_card(CardIdx_t card_index) const {
 #if UNROLL_CARD_LOOPS
   assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   if (_cards[0] == card_index) return true;
@@ -80,10 +81,10 @@
   return sum;
 }
 
-SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(short card_index) {
+SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) {
 #if UNROLL_CARD_LOOPS
   assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
-  short c = _cards[0];
+  CardIdx_t c = _cards[0];
   if (c == card_index) return found;
   if (c == NullEntry) { _cards[0] = card_index; return added; }
   c = _cards[1];
@@ -97,16 +98,19 @@
   if (c == NullEntry) { _cards[3] = card_index; return added; }
 #else
   for (int i = 0; i < CardsPerEntry; i++) {
-    short c = _cards[i];
+    CardIdx_t c = _cards[i];
     if (c == card_index) return found;
-    if (c == NullEntry) { _cards[i] = card_index; return added; }
+    if (c == NullEntry) {
+      _cards[i] = card_index;
+      return added;
+    }
   }
 #endif
   // Otherwise, we're full.
   return overflow;
 }
 
-void SparsePRTEntry::copy_cards(short* cards) const {
+void SparsePRTEntry::copy_cards(CardIdx_t* cards) const {
 #if UNROLL_CARD_LOOPS
   assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   cards[0] = _cards[0];
@@ -130,7 +134,7 @@
   _capacity(capacity), _capacity_mask(capacity-1),
   _occupied_entries(0), _occupied_cards(0),
   _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)),
-  _buckets(NEW_C_HEAP_ARRAY(short, capacity)),
+  _buckets(NEW_C_HEAP_ARRAY(int, capacity)),
   _next_deleted(NULL), _deleted(false),
   _free_list(NullEntry), _free_region(0)
 {
@@ -143,7 +147,7 @@
     _entries = NULL;
   }
   if (_buckets != NULL) {
-    FREE_C_HEAP_ARRAY(short, _buckets);
+    FREE_C_HEAP_ARRAY(int, _buckets);
     _buckets = NULL;
   }
 }
@@ -153,14 +157,18 @@
   _occupied_cards = 0;
   guarantee(_entries != NULL, "INV");
   guarantee(_buckets != NULL, "INV");
+
+  guarantee(_capacity <= ((size_t)1 << (sizeof(int)*BitsPerByte-1)) - 1,
+                "_capacity too large");
+
   // This will put -1 == NullEntry in the key field of all entries.
   memset(_entries, -1, _capacity * sizeof(SparsePRTEntry));
-  memset(_buckets, -1, _capacity * sizeof(short));
+  memset(_buckets, -1, _capacity * sizeof(int));
   _free_list = NullEntry;
   _free_region = 0;
 }
 
-bool RSHashTable::add_card(short region_ind, short card_index) {
+bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) {
   SparsePRTEntry* e = entry_for_region_ind_create(region_ind);
   assert(e != NULL && e->r_ind() == region_ind,
          "Postcondition of call above.");
@@ -175,9 +183,9 @@
   return res != SparsePRTEntry::overflow;
 }
 
-bool RSHashTable::get_cards(short region_ind, short* cards) {
-  short ind = (short) (region_ind & capacity_mask());
-  short cur_ind = _buckets[ind];
+bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) {
+  int ind = (int) (region_ind & capacity_mask());
+  int cur_ind = _buckets[ind];
   SparsePRTEntry* cur;
   while (cur_ind != NullEntry &&
          (cur = entry(cur_ind))->r_ind() != region_ind) {
@@ -192,10 +200,10 @@
   return true;
 }
 
-bool RSHashTable::delete_entry(short region_ind) {
-  short ind = (short) (region_ind & capacity_mask());
-  short* prev_loc = &_buckets[ind];
-  short cur_ind = *prev_loc;
+bool RSHashTable::delete_entry(RegionIdx_t region_ind) {
+  int ind = (int) (region_ind & capacity_mask());
+  int* prev_loc = &_buckets[ind];
+  int cur_ind = *prev_loc;
   SparsePRTEntry* cur;
   while (cur_ind != NullEntry &&
          (cur = entry(cur_ind))->r_ind() != region_ind) {
@@ -212,10 +220,11 @@
   return true;
 }
 
-SparsePRTEntry* RSHashTable::entry_for_region_ind(short region_ind) const {
+SparsePRTEntry*
+RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const {
   assert(occupied_entries() < capacity(), "Precondition");
-  short ind = (short) (region_ind & capacity_mask());
-  short cur_ind = _buckets[ind];
+  int ind = (int) (region_ind & capacity_mask());
+  int cur_ind = _buckets[ind];
   SparsePRTEntry* cur;
   // XXX
   // int k = 0;
@@ -242,15 +251,16 @@
   }
 }
 
-SparsePRTEntry* RSHashTable::entry_for_region_ind_create(short region_ind) {
+SparsePRTEntry*
+RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) {
   SparsePRTEntry* res = entry_for_region_ind(region_ind);
   if (res == NULL) {
-    short new_ind = alloc_entry();
+    int new_ind = alloc_entry();
     assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room.");
     res = entry(new_ind);
     res->init(region_ind);
     // Insert at front.
-    short ind = (short) (region_ind & capacity_mask());
+    int ind = (int) (region_ind & capacity_mask());
     res->set_next_index(_buckets[ind]);
     _buckets[ind] = new_ind;
     _occupied_entries++;
@@ -258,8 +268,8 @@
   return res;
 }
 
-short RSHashTable::alloc_entry() {
-  short res;
+int RSHashTable::alloc_entry() {
+  int res;
   if (_free_list != NullEntry) {
     res = _free_list;
     _free_list = entry(res)->next_index();
@@ -273,13 +283,11 @@
   }
 }
 
-
-void RSHashTable::free_entry(short fi) {
+void RSHashTable::free_entry(int fi) {
   entry(fi)->set_next_index(_free_list);
   _free_list = fi;
 }
 
-
 void RSHashTable::add_entry(SparsePRTEntry* e) {
   assert(e->num_valid_cards() > 0, "Precondition.");
   SparsePRTEntry* e2 = entry_for_region_ind_create(e->r_ind());
@@ -322,8 +330,8 @@
   return NULL;
 }
 
-short /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
-  short res;
+CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
+  CardIdx_t res;
   while (_bl_ind != RSHashTable::NullEntry) {
     res = _rsht->entry(_bl_ind)->card(0);
     if (res != SparsePRTEntry::NullEntry) {
@@ -336,7 +344,7 @@
   return SparsePRTEntry::NullEntry;
 }
 
-size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(short ci) {
+size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) {
   return
     _heap_bot_card_ind
     + (_rsht->entry(_bl_ind)->r_ind() * CardsPerRegion)
@@ -345,7 +353,7 @@
 
 bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
   _card_ind++;
-  short ci;
+  CardIdx_t ci;
   if (_card_ind < SparsePRTEntry::CardsPerEntry &&
       ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) !=
        SparsePRTEntry::NullEntry)) {
@@ -379,16 +387,16 @@
   return false;
 }
 
-bool RSHashTable::contains_card(short region_index, short card_index) const {
+bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const {
   SparsePRTEntry* e = entry_for_region_ind(region_index);
   return (e != NULL && e->contains_card(card_index));
 }
 
 size_t RSHashTable::mem_size() const {
-  return sizeof(this) + capacity() * (sizeof(SparsePRTEntry) + sizeof(short));
+  return sizeof(this) +
+    capacity() * (sizeof(SparsePRTEntry) + sizeof(int));
 }
 
-
 // ----------------------------------------------------------------------
 
 SparsePRT* SparsePRT::_head_expanded_list = NULL;
@@ -408,6 +416,7 @@
   }
 }
 
+
 SparsePRT* SparsePRT::get_from_expanded_list() {
   SparsePRT* hd = _head_expanded_list;
   while (hd != NULL) {
@@ -452,6 +461,7 @@
   _next = _cur;
 }
 
+
 SparsePRT::~SparsePRT() {
   assert(_next != NULL && _cur != NULL, "Inv");
   if (_cur != _next) { delete _cur; }
@@ -465,7 +475,7 @@
   return sizeof(this) + _next->mem_size();
 }
 
-bool SparsePRT::add_card(short region_id, short card_index) {
+bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
 #if SPARSE_PRT_VERBOSE
   gclog_or_tty->print_cr("  Adding card %d from region %d to region %d sparse.",
                 card_index, region_id, _hr->hrs_index());
@@ -476,11 +486,11 @@
   return _next->add_card(region_id, card_index);
 }
 
-bool SparsePRT::get_cards(short region_id, short* cards) {
+bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) {
   return _next->get_cards(region_id, cards);
 }
 
-bool SparsePRT::delete_entry(short region_id) {
+bool SparsePRT::delete_entry(RegionIdx_t region_id) {
   return _next->delete_entry(region_id);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -35,32 +35,32 @@
 
 class SparsePRTEntry: public CHeapObj {
 public:
+
   enum SomePublicConstants {
-    CardsPerEntry = (short)4,
-    NullEntry = (short)-1,
-    DeletedEntry = (short)-2
+    CardsPerEntry =  4,
+    NullEntry     = -1
   };
 
 private:
-  short _region_ind;
-  short _next_index;
-  short _cards[CardsPerEntry];
+  RegionIdx_t _region_ind;
+  int         _next_index;
+  CardIdx_t   _cards[CardsPerEntry];
 
 public:
 
   // Set the region_ind to the given value, and delete all cards.
-  inline void init(short region_ind);
+  inline void init(RegionIdx_t region_ind);
 
-  short r_ind() const { return _region_ind; }
+  RegionIdx_t r_ind() const { return _region_ind; }
   bool valid_entry() const { return r_ind() >= 0; }
-  void set_r_ind(short rind) { _region_ind = rind; }
+  void set_r_ind(RegionIdx_t rind) { _region_ind = rind; }
 
-  short next_index() const { return _next_index; }
-  short* next_index_addr() { return &_next_index; }
-  void set_next_index(short ni) { _next_index = ni; }
+  int next_index() const { return _next_index; }
+  int* next_index_addr() { return &_next_index; }
+  void set_next_index(int ni) { _next_index = ni; }
 
   // Returns "true" iff the entry contains the given card index.
-  inline bool contains_card(short card_index) const;
+  inline bool contains_card(CardIdx_t card_index) const;
 
   // Returns the number of non-NULL card entries.
   inline int num_valid_cards() const;
@@ -73,14 +73,14 @@
     found,
     added
   };
-  inline AddCardResult add_card(short card_index);
+  inline AddCardResult add_card(CardIdx_t card_index);
 
   // Copy the current entry's cards into "cards".
-  inline void copy_cards(short* cards) const;
+  inline void copy_cards(CardIdx_t* cards) const;
   // Copy the current entry's cards into the "_card" array of "e."
   inline void copy_cards(SparsePRTEntry* e) const;
 
-  inline short card(int i) const { return _cards[i]; }
+  inline CardIdx_t card(int i) const { return _cards[i]; }
 };
 
 
@@ -98,9 +98,9 @@
   size_t _occupied_cards;
 
   SparsePRTEntry* _entries;
-  short* _buckets;
-  short  _free_region;
-  short  _free_list;
+  int* _buckets;
+  int  _free_region;
+  int  _free_list;
 
   static RSHashTable* _head_deleted_list;
   RSHashTable* _next_deleted;
@@ -113,20 +113,20 @@
   // operations, and that the the table be less than completely full.  If
   // an entry for "region_ind" is already in the table, finds it and
   // returns its address; otherwise returns "NULL."
-  SparsePRTEntry* entry_for_region_ind(short region_ind) const;
+  SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
 
   // Requires that the caller hold a lock preventing parallel modifying
   // operations, and that the the table be less than completely full.  If
   // an entry for "region_ind" is already in the table, finds it and
   // returns its address; otherwise allocates, initializes, inserts and
   // returns a new entry for "region_ind".
-  SparsePRTEntry* entry_for_region_ind_create(short region_ind);
+  SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
 
   // Returns the index of the next free entry in "_entries".
-  short alloc_entry();
+  int alloc_entry();
   // Declares the entry "fi" to be free.  (It must have already been
   // deleted from any bucket lists.
-  void free_entry(short fi);
+  void free_entry(int fi);
 
 public:
   RSHashTable(size_t capacity);
@@ -138,12 +138,12 @@
   // Otherwise, returns "false" to indicate that the addition would
   // overflow the entry for the region.  The caller must transfer these
   // entries to a larger-capacity representation.
-  bool add_card(short region_id, short card_index);
+  bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
 
-  bool get_cards(short region_id, short* cards);
-  bool delete_entry(short region_id);
+  bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
+  bool delete_entry(RegionIdx_t region_id);
 
-  bool contains_card(short region_id, short card_index) const;
+  bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
 
   void add_entry(SparsePRTEntry* e);
 
@@ -162,51 +162,49 @@
 
   static void add_to_deleted_list(RSHashTable* rsht);
   static RSHashTable* get_from_deleted_list();
-
-
 };
 
-  // ValueObj because will be embedded in HRRS iterator.
+// ValueObj because will be embedded in HRRS iterator.
 class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
-    short _tbl_ind;
-    short _bl_ind;
-    short _card_ind;
-    RSHashTable* _rsht;
-    size_t _heap_bot_card_ind;
+  int _tbl_ind;         // [-1, 0.._rsht->_capacity)
+  int _bl_ind;          // [-1, 0.._rsht->_capacity)
+  short _card_ind;      // [0..CardsPerEntry)
+  RSHashTable* _rsht;
+  size_t _heap_bot_card_ind;
 
-    enum SomePrivateConstants {
-      CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift
-    };
+  enum SomePrivateConstants {
+    CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift
+  };
+
+  // If the bucket list pointed to by _bl_ind contains a card, sets
+  // _bl_ind to the index of that entry, and returns the card.
+  // Otherwise, returns SparseEntry::NullEntry.
+  CardIdx_t find_first_card_in_list();
 
-    // If the bucket list pointed to by _bl_ind contains a card, sets
-    // _bl_ind to the index of that entry, and returns the card.
-    // Otherwise, returns SparseEntry::NullEnty.
-    short find_first_card_in_list();
-    // Computes the proper card index for the card whose offset in the
-    // current region (as indicated by _bl_ind) is "ci".
-    // This is subject to errors when there is iteration concurrent with
-    // modification, but these errors should be benign.
-    size_t compute_card_ind(short ci);
+  // Computes the proper card index for the card whose offset in the
+  // current region (as indicated by _bl_ind) is "ci".
+  // This is subject to errors when there is iteration concurrent with
+  // modification, but these errors should be benign.
+  size_t compute_card_ind(CardIdx_t ci);
 
-  public:
-    RSHashTableIter(size_t heap_bot_card_ind) :
-      _tbl_ind(RSHashTable::NullEntry),
-      _bl_ind(RSHashTable::NullEntry),
-      _card_ind((SparsePRTEntry::CardsPerEntry-1)),
-      _rsht(NULL),
-      _heap_bot_card_ind(heap_bot_card_ind)
-    {}
+public:
+  RSHashTableIter(size_t heap_bot_card_ind) :
+    _tbl_ind(RSHashTable::NullEntry),
+    _bl_ind(RSHashTable::NullEntry),
+    _card_ind((SparsePRTEntry::CardsPerEntry-1)),
+    _rsht(NULL),
+    _heap_bot_card_ind(heap_bot_card_ind)
+  {}
 
-    void init(RSHashTable* rsht) {
-      _rsht = rsht;
-      _tbl_ind = -1; // So that first increment gets to 0.
-      _bl_ind = RSHashTable::NullEntry;
-      _card_ind = (SparsePRTEntry::CardsPerEntry-1);
-    }
+  void init(RSHashTable* rsht) {
+    _rsht = rsht;
+    _tbl_ind = -1; // So that first increment gets to 0.
+    _bl_ind = RSHashTable::NullEntry;
+    _card_ind = (SparsePRTEntry::CardsPerEntry-1);
+  }
 
-    bool has_next(size_t& card_index);
-
-  };
+  bool has_next(size_t& card_index);
+};
 
 // Concurrent accesss to a SparsePRT must be serialized by some external
 // mutex.
@@ -238,7 +236,6 @@
   SparsePRT* next_expanded() { return _next_expanded; }
   void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
 
-
   static SparsePRT* _head_expanded_list;
 
 public:
@@ -255,16 +252,16 @@
   // Otherwise, returns "false" to indicate that the addition would
   // overflow the entry for the region.  The caller must transfer these
   // entries to a larger-capacity representation.
-  bool add_card(short region_id, short card_index);
+  bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
 
   // If the table hold an entry for "region_ind",  Copies its
   // cards into "cards", which must be an array of length at least
   // "CardsPerEntry", and returns "true"; otherwise, returns "false".
-  bool get_cards(short region_ind, short* cards);
+  bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
 
   // If there is an entry for "region_ind", removes it and return "true";
   // otherwise returns "false."
-  bool delete_entry(short region_ind);
+  bool delete_entry(RegionIdx_t region_ind);
 
   // Clear the table, and reinitialize to initial capacity.
   void clear();
@@ -276,13 +273,12 @@
   static void cleanup_all();
   RSHashTable* cur() const { return _cur; }
 
-
   void init_iterator(SparsePRTIter* sprt_iter);
 
   static void add_to_expanded_list(SparsePRT* sprt);
   static SparsePRT* get_from_expanded_list();
 
-  bool contains_card(short region_id, short card_index) const {
+  bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
     return _next->contains_card(region_id, card_index);
   }
 
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 16:55:26 2017 +0200
@@ -51,7 +51,6 @@
 concurrentG1Refine.hpp			allocation.hpp
 concurrentG1Refine.hpp			thread.hpp
 
-
 concurrentG1RefineThread.cpp		concurrentG1Refine.hpp
 concurrentG1RefineThread.cpp		concurrentG1RefineThread.hpp
 concurrentG1RefineThread.cpp		g1CollectedHeap.inline.hpp
@@ -334,6 +333,7 @@
 sparsePRT.hpp				allocation.hpp
 sparsePRT.hpp				cardTableModRefBS.hpp
 sparsePRT.hpp				globalDefinitions.hpp
+sparsePRT.hpp                           g1CollectedHeap.inline.hpp
 sparsePRT.hpp				heapRegion.hpp
 sparsePRT.hpp				mutex.hpp
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -177,6 +177,7 @@
   // are double-word aligned in 32-bit VMs, but not in 64-bit VMs, so the 32-bit
   // granularity is 2, 64-bit is 1.
   static inline size_t obj_granularity() { return size_t(MinObjAlignment); }
+  static inline int obj_granularity_shift() { return LogMinObjAlignment; }
 
   HeapWord*       _region_start;
   size_t          _region_size;
@@ -299,13 +300,13 @@
 inline size_t
 ParMarkBitMap::bits_to_words(idx_t bits)
 {
-  return bits * obj_granularity();
+  return bits << obj_granularity_shift();
 }
 
 inline ParMarkBitMap::idx_t
 ParMarkBitMap::words_to_bits(size_t words)
 {
-  return words / obj_granularity();
+  return words >> obj_granularity_shift();
 }
 
 inline size_t ParMarkBitMap::obj_size(idx_t beg_bit, idx_t end_bit) const
--- a/hotspot/src/share/vm/includeDB_compiler1	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_compiler1	Wed Jul 05 16:55:26 2017 +0200
@@ -387,7 +387,7 @@
 c1_ValueSet.cpp                         c1_ValueSet.hpp
 
 c1_ValueSet.hpp                         allocation.hpp
-c1_ValueSet.hpp                         bitMap.hpp
+c1_ValueSet.hpp                         bitMap.inline.hpp
 c1_ValueSet.hpp                         c1_Instruction.hpp
 
 c1_ValueStack.cpp                       c1_IR.hpp
--- a/hotspot/src/share/vm/memory/gcLocker.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/memory/gcLocker.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -242,6 +242,31 @@
 #endif
 };
 
+// A SkipGCALot object is used to elide the usual effect of gc-a-lot
+// over a section of execution by a thread. Currently, it's used only to
+// prevent re-entrant calls to GC.
+class SkipGCALot : public StackObj {
+  private:
+   bool _saved;
+   Thread* _t;
+
+  public:
+#ifdef ASSERT
+    SkipGCALot(Thread* t) : _t(t) {
+      _saved = _t->skip_gcalot();
+      _t->set_skip_gcalot(true);
+    }
+
+    ~SkipGCALot() {
+      assert(_t->skip_gcalot(), "Save-restore protocol invariant");
+      _t->set_skip_gcalot(_saved);
+    }
+#else
+    SkipGCALot(Thread* t) { }
+    ~SkipGCALot() { }
+#endif
+};
+
 // JRT_LEAF currently can be called from either _thread_in_Java or
 // _thread_in_native mode. In _thread_in_native, it is ok
 // for another thread to trigger GC. The rest of the JRT_LEAF
--- a/hotspot/src/share/vm/runtime/interfaceSupport.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -66,11 +66,14 @@
 
 void InterfaceSupport::gc_alot() {
   Thread *thread = Thread::current();
-  if (thread->is_VM_thread()) return; // Avoid concurrent calls
+  if (!thread->is_Java_thread()) return; // Avoid concurrent calls
   // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.
   JavaThread *current_thread = (JavaThread *)thread;
   if (current_thread->active_handles() == NULL) return;
 
+  // Short-circuit any possible re-entrant gc-a-lot attempt
+  if (thread->skip_gcalot()) return;
+
   if (is_init_completed()) {
 
     if (++_fullgc_alot_invocation < FullGCALotStart) {
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -127,6 +127,7 @@
   debug_only(_owned_locks = NULL;)
   debug_only(_allow_allocation_count = 0;)
   NOT_PRODUCT(_allow_safepoint_count = 0;)
+  NOT_PRODUCT(_skip_gcalot = false;)
   CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
   _jvmti_env_iteration_count = 0;
   _vm_operation_started_count = 0;
@@ -784,7 +785,6 @@
       // We could enter a safepoint here and thus have a gc
       InterfaceSupport::check_gc_alot();
     }
-
 #endif
 }
 #endif
--- a/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -191,6 +191,9 @@
   NOT_PRODUCT(int _allow_safepoint_count;)       // If 0, thread allow a safepoint to happen
   debug_only (int _allow_allocation_count;)      // If 0, the thread is allowed to allocate oops.
 
+  // Used by SkipGCALot class.
+  NOT_PRODUCT(bool _skip_gcalot;)                // Should we elide gc-a-lot?
+
   // Record when GC is locked out via the GC_locker mechanism
   CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;)
 
@@ -308,6 +311,11 @@
   bool is_gc_locked_out() { return _gc_locked_out_count > 0; }
 #endif // CHECK_UNHANDLED_OOPS
 
+#ifndef PRODUCT
+  bool skip_gcalot()           { return _skip_gcalot; }
+  void set_skip_gcalot(bool v) { _skip_gcalot = v;    }
+#endif
+
  public:
   // Installs a pending exception to be inserted later
   static void send_async_exception(oop thread_oop, oop java_throwable);
--- a/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -531,6 +531,7 @@
   Thread* t = Thread::current();
 
   if (!t->is_VM_thread()) {
+    SkipGCALot sgcalot(t);    // avoid re-entrant attempts to gc-a-lot
     // JavaThread or WatcherThread
     t->check_for_valid_safepoint_state(true);
 
--- a/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Jul 05 16:55:26 2017 +0200
@@ -41,19 +41,6 @@
   resize(size_in_bits, in_resource_area);
 }
 
-
-void BitMap::verify_index(idx_t index) const {
-    assert(index < _size, "BitMap index out of bounds");
-}
-
-void BitMap::verify_range(idx_t beg_index, idx_t end_index) const {
-#ifdef ASSERT
-    assert(beg_index <= end_index, "BitMap range error");
-    // Note that [0,0) and [size,size) are both valid ranges.
-    if (end_index != _size)  verify_index(end_index);
-#endif
-}
-
 void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
   assert(size_in_bits >= 0, "just checking");
   idx_t old_size_in_words = size_in_words();
--- a/hotspot/src/share/vm/utilities/bitMap.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -93,10 +93,12 @@
   // The index of the first full word in a range.
   idx_t word_index_round_up(idx_t bit) const;
 
-  // Verification, statistics.
-  void verify_index(idx_t index) const;
-  void verify_range(idx_t beg_index, idx_t end_index) const;
+  // Verification.
+  inline void verify_index(idx_t index) const NOT_DEBUG_RETURN;
+  inline void verify_range(idx_t beg_index, idx_t end_index) const
+    NOT_DEBUG_RETURN;
 
+  // Statistics.
   static idx_t* _pop_count_table;
   static void init_pop_count_table();
   static idx_t num_set_bits(bm_word_t w);
@@ -287,7 +289,6 @@
 #endif
 };
 
-
 // Convenience class wrapping BitMap which provides multiple bits per slot.
 class BitMap2D VALUE_OBJ_CLASS_SPEC {
  public:
--- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -22,6 +22,17 @@
  *
  */
 
+#ifdef ASSERT
+inline void BitMap::verify_index(idx_t index) const {
+  assert(index < _size, "BitMap index out of bounds");
+}
+
+inline void BitMap::verify_range(idx_t beg_index, idx_t end_index) const {
+  assert(beg_index <= end_index, "BitMap range error");
+  // Note that [0,0) and [size,size) are both valid ranges.
+  if (end_index != _size) verify_index(end_index);
+}
+#endif // #ifdef ASSERT
 
 inline void BitMap::set_bit(idx_t bit) {
   verify_index(bit);
--- a/hotspot/src/share/vm/utilities/macros.hpp	Wed Jul 05 16:55:03 2017 +0200
+++ b/hotspot/src/share/vm/utilities/macros.hpp	Wed Jul 05 16:55:26 2017 +0200
@@ -106,11 +106,13 @@
 #ifdef ASSERT
 #define DEBUG_ONLY(code) code
 #define NOT_DEBUG(code)
+#define NOT_DEBUG_RETURN  /*next token must be ;*/
 // Historical.
 #define debug_only(code) code
 #else // ASSERT
 #define DEBUG_ONLY(code)
 #define NOT_DEBUG(code) code
+#define NOT_DEBUG_RETURN {}
 #define debug_only(code)
 #endif // ASSERT
 
--- a/jaxp/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 75113d7ce083048e7576b9d0d60a4e80db6b181f jdk7-b59
 259aef5045a155eb6a2f8dd0e2429c6dbe0f652f jdk7-b60
 f1ac756616eaaad795f77f7f5e7f7c7bfdc9c1de jdk7-b61
+a97dd57a62604c35c79bc2fa77a612ed547f6135 jdk7-b62
--- a/jaxws/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 f64566bf4c2bc92e65ab2b9fab51b119f0d493d1 jdk7-b59
 3b054db3e277ca224fe6576c59ed6f4ab5ed0bb5 jdk7-b60
 aeabf802f2a1ca72b87d7397c5ece58058e000a9 jdk7-b61
+75c801c13ea1ddebc58b1a8c8da9318d72750e62 jdk7-b62
--- a/jdk/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 2a5a1b269e89f27ebe419ef4cf6e66a3face0df1 jdk7-b59
 0c3ef2d612a47667829eb17a192decef23f1c536 jdk7-b60
 f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61
+12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62
--- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java	Wed Jul 05 16:55:26 2017 +0200
@@ -506,6 +506,19 @@
 
         writeFileHeader(fileSize, offset);
 
+        /* According to MSDN description, the top-down image layout
+         * is allowed only if compression type is BI_RGB or BI_BITFIELDS.
+         * Images with any other compression type must be wrote in the
+         * bottom-up layout.
+         */
+        if (compressionType == BMPConstants.BI_RGB ||
+            compressionType == BMPConstants.BI_BITFIELDS)
+        {
+            isTopDown = bmpParam.isTopDown();
+        } else {
+            isTopDown = false;
+        }
+
         writeInfoHeader(headerSize, bitsPerPixel);
 
         // compression
@@ -588,8 +601,6 @@
             return;
         }
 
-        isTopDown = bmpParam.isTopDown();
-
         int maxBandOffset = bandOffsets[0];
         for (int i = 1; i < bandOffsets.length; i++)
             if (bandOffsets[i] > maxBandOffset)
@@ -1299,7 +1310,7 @@
         stream.writeInt(w);
 
         // height
-        stream.writeInt(h);
+        stream.writeInt(isTopDown ? -h : h);
 
         // number of planes
         stream.writeShort(1);
--- a/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java	Wed Jul 05 16:55:26 2017 +0200
@@ -27,6 +27,8 @@
 
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.io.IOException;
+import javax.imageio.stream.ImageInputStream;
 
 /**
  * This class contains utility methods that may be useful to ImageReader
@@ -198,4 +200,17 @@
                              vals, 1);
         return vals;
     }
+
+    public static int readMultiByteInteger(ImageInputStream iis)
+        throws IOException
+    {
+        int value = iis.readByte();
+        int result = value & 0x7f;
+        while((value & 0x80) == 0x80) {
+            result <<= 7;
+            value = iis.readByte();
+            result |= (value & 0x7f);
+        }
+        return result;
+    }
 }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Wed Jul 05 16:55:26 2017 +0200
@@ -215,17 +215,21 @@
     public static class JCS {
         public static final ColorSpace sRGB =
             ColorSpace.getInstance(ColorSpace.CS_sRGB);
-        public static final ColorSpace YCC;
+
+        private static ColorSpace YCC = null;
+        private static boolean yccInited = false;
 
-        static {
-            ColorSpace cs = null;
-            try {
-                cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
-            } catch (IllegalArgumentException e) {
-                // PYCC.pf may not always be installed
-            } finally {
-                YCC = cs;
+        public static ColorSpace getYCC() {
+            if (!yccInited) {
+                try {
+                    YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
+                } catch (IllegalArgumentException e) {
+                    // PYCC.pf may not always be installed
+                } finally {
+                    yccInited = true;
+                }
             }
+            return YCC;
         }
     }
 
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 16:55:26 2017 +0200
@@ -41,6 +41,7 @@
 import java.awt.color.ColorSpace;
 import java.awt.color.ICC_Profile;
 import java.awt.color.ICC_ColorSpace;
+import java.awt.color.CMMException;
 import java.awt.image.BufferedImage;
 import java.awt.image.Raster;
 import java.awt.image.WritableRaster;
@@ -53,6 +54,7 @@
 import java.util.List;
 import java.util.Iterator;
 import java.util.ArrayList;
+import java.util.NoSuchElementException;
 
 import sun.java2d.Disposer;
 import sun.java2d.DisposerRecord;
@@ -215,51 +217,6 @@
     /** The DisposerRecord that handles the actual disposal of this reader. */
     private DisposerRecord disposerRecord;
 
-    /**
-     * Maintain an array of the default image types corresponding to the
-     * various supported IJG colorspace codes.
-     */
-    private static final ImageTypeSpecifier [] defaultTypes =
-        new ImageTypeSpecifier [JPEG.NUM_JCS_CODES];
-
-    static {
-        defaultTypes[JPEG.JCS_GRAYSCALE] =
-            ImageTypeSpecifier.createFromBufferedImageType
-            (BufferedImage.TYPE_BYTE_GRAY);
-        defaultTypes[JPEG.JCS_RGB] =
-            ImageTypeSpecifier.createInterleaved
-            (JPEG.JCS.sRGB,
-             JPEG.bOffsRGB,
-             DataBuffer.TYPE_BYTE,
-             false,
-             false);
-        defaultTypes[JPEG.JCS_RGBA] =
-            ImageTypeSpecifier.createPacked
-            (JPEG.JCS.sRGB,
-             0xff000000,
-             0x00ff0000,
-             0x0000ff00,
-             0x000000ff,
-             DataBuffer.TYPE_INT,
-             false);
-        if (JPEG.JCS.YCC != null) {
-            defaultTypes[JPEG.JCS_YCC] =
-                ImageTypeSpecifier.createInterleaved
-                (JPEG.JCS.YCC,
-                 JPEG.bandOffsets[2],
-                 DataBuffer.TYPE_BYTE,
-                 false,
-                 false);
-            defaultTypes[JPEG.JCS_YCCA] =
-                ImageTypeSpecifier.createInterleaved
-                (JPEG.JCS.YCC,
-                 JPEG.bandOffsets[3],
-                 DataBuffer.TYPE_BYTE,
-                 true,
-                 false);
-        }
-    }
-
     /** Sets up static C structures. */
     private static native void initReaderIDs(Class iisClass,
                                              Class qTableClass,
@@ -673,6 +630,17 @@
             !java.util.Arrays.equals(oldData, newData))
         {
             iccCS = new ICC_ColorSpace(newProfile);
+            // verify new color space
+            try {
+                float[] colors = iccCS.fromRGB(new float[] {1f, 0f, 0f});
+            } catch (CMMException e) {
+                /*
+                 * Embedded profile seems to be corrupted.
+                 * Ignore this profile.
+                 */
+                iccCS = null;
+                warningOccurred(WARNING_IGNORE_INVALID_ICC);
+            }
         }
     }
 
@@ -706,11 +674,11 @@
      * Return an ImageTypeSpecifier corresponding to the given
      * color space code, or null if the color space is unsupported.
      */
-    private ImageTypeSpecifier getImageType(int code) {
-        ImageTypeSpecifier ret = null;
+    private ImageTypeProducer getImageType(int code) {
+        ImageTypeProducer ret = null;
 
         if ((code > 0) && (code < JPEG.NUM_JCS_CODES)) {
-            ret = defaultTypes[code];
+            ret = ImageTypeProducer.getTypeProducer(code);
         }
         return ret;
     }
@@ -724,7 +692,7 @@
             }
 
             // Returns null if it can't be represented
-            return getImageType(colorSpaceCode);
+            return getImageType(colorSpaceCode).getType();
         } finally {
             clearThreadLock();
         }
@@ -758,13 +726,13 @@
 
         // Get the raw ITS, if there is one.  Note that this
         // won't always be the same as the default.
-        ImageTypeSpecifier raw = getImageType(colorSpaceCode);
+        ImageTypeProducer raw = getImageType(colorSpaceCode);
 
         // Given the encoded colorspace, build a list of ITS's
         // representing outputs you could handle starting
         // with the default.
 
-        ArrayList list = new ArrayList(1);
+        ArrayList<ImageTypeProducer> list = new ArrayList<ImageTypeProducer>(1);
 
         switch (colorSpaceCode) {
         case JPEG.JCS_GRAYSCALE:
@@ -774,9 +742,7 @@
         case JPEG.JCS_RGB:
             list.add(raw);
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.JCS.YCC != null) {
-                list.add(getImageType(JPEG.JCS_YCC));
-            }
+            list.add(getImageType(JPEG.JCS_YCC));
             break;
         case JPEG.JCS_RGBA:
             list.add(raw);
@@ -801,19 +767,21 @@
             list.add(getImageType(JPEG.JCS_RGB));
 
             if (iccCS != null) {
-                list.add(ImageTypeSpecifier.createInterleaved
+                list.add(new ImageTypeProducer() {
+                    protected ImageTypeSpecifier produce() {
+                        return ImageTypeSpecifier.createInterleaved
                          (iccCS,
                           JPEG.bOffsRGB,  // Assume it's for RGB
                           DataBuffer.TYPE_BYTE,
                           false,
-                          false));
+                          false);
+                    }
+                });
 
             }
 
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed
-                list.add(getImageType(JPEG.JCS_YCC));
-            }
+            list.add(getImageType(JPEG.JCS_YCC));
             break;
         case JPEG.JCS_YCbCrA:  // Default is to convert to RGBA
             // As there is no YCbCr ColorSpace, we can't support
@@ -822,7 +790,7 @@
             break;
         }
 
-        return list.iterator();
+        return new ImageTypeIterator(list.iterator());
     }
 
     /**
@@ -872,6 +840,10 @@
             if  (csType == ColorSpace.TYPE_RGB) { // We want RGB
                 // IJG can do this for us more efficiently
                 setOutColorSpace(structPointer, JPEG.JCS_RGB);
+                // Update java state according to changes
+                // in the native part of decoder.
+                outColorSpaceCode = JPEG.JCS_RGB;
+                numComponents = 3;
             } else if (csType != ColorSpace.TYPE_GRAY) {
                 throw new IIOException("Incompatible color conversion");
             }
@@ -881,6 +853,10 @@
                 if (colorSpaceCode == JPEG.JCS_YCbCr) {
                     // If the jpeg space is YCbCr, IJG can do it
                     setOutColorSpace(structPointer, JPEG.JCS_GRAYSCALE);
+                    // Update java state according to changes
+                    // in the native part of decoder.
+                    outColorSpaceCode = JPEG.JCS_GRAYSCALE;
+                    numComponents = 1;
                 }
             } else if ((iccCS != null) &&
                        (cm.getNumComponents() == numComponents) &&
@@ -906,20 +882,26 @@
             }
             break;
         case JPEG.JCS_YCC:
-            if (JPEG.JCS.YCC == null) { // We can't do YCC at all
-                throw new IIOException("Incompatible color conversion");
-            }
-            if ((cs != JPEG.JCS.YCC) &&
-                (cm.getNumComponents() == numComponents)) {
-                convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null);
+            {
+                ColorSpace YCC = JPEG.JCS.getYCC();
+                if (YCC == null) { // We can't do YCC at all
+                    throw new IIOException("Incompatible color conversion");
+                }
+                if ((cs != YCC) &&
+                    (cm.getNumComponents() == numComponents)) {
+                    convert = new ColorConvertOp(YCC, cs, null);
+                }
             }
             break;
         case JPEG.JCS_YCCA:
-            // No conversions available; image must be YCCA
-            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");
+            {
+                ColorSpace YCC = JPEG.JCS.getYCC();
+                // No conversions available; image must be YCCA
+                if ((YCC == null) || // We can't do YCC at all
+                    (cs != YCC) ||
+                    (cm.getNumComponents() != numComponents)) {
+                    throw new IIOException("Incompatible color conversion");
+                }
             }
             break;
         default:
@@ -1554,3 +1536,140 @@
         }
     }
 }
+
+/**
+ * An internal helper class that wraps producer's iterator
+ * and extracts specifier instances on demand.
+ */
+class ImageTypeIterator implements Iterator<ImageTypeSpecifier> {
+     private Iterator<ImageTypeProducer> producers;
+     private ImageTypeSpecifier theNext = null;
+
+     public ImageTypeIterator(Iterator<ImageTypeProducer> producers) {
+         this.producers = producers;
+     }
+
+     public boolean hasNext() {
+         if (theNext != null) {
+             return true;
+         }
+         if (!producers.hasNext()) {
+             return false;
+         }
+         do {
+             theNext = producers.next().getType();
+         } while (theNext == null && producers.hasNext());
+
+         return (theNext != null);
+     }
+
+     public ImageTypeSpecifier next() {
+         if (theNext != null || hasNext()) {
+             ImageTypeSpecifier t = theNext;
+             theNext = null;
+             return t;
+         } else {
+             throw new NoSuchElementException();
+         }
+     }
+
+     public void remove() {
+         producers.remove();
+     }
+}
+
+/**
+ * An internal helper class that provides means for deferred creation
+ * of ImageTypeSpecifier instance required to describe available
+ * destination types.
+ *
+ * This implementation only supports standard
+ * jpeg color spaces (defined by corresponding JCS color space code).
+ *
+ * To support other color spaces one can override produce() method to
+ * return custom instance of ImageTypeSpecifier.
+ */
+class ImageTypeProducer {
+
+    private ImageTypeSpecifier type = null;
+    boolean failed = false;
+    private int csCode;
+
+    public ImageTypeProducer(int csCode) {
+        this.csCode = csCode;
+    }
+
+    public ImageTypeProducer() {
+        csCode = -1; // undefined
+    }
+
+    public synchronized ImageTypeSpecifier getType() {
+        if (!failed && type == null) {
+            try {
+                type = produce();
+            } catch (Throwable e) {
+                failed = true;
+            }
+        }
+        return type;
+    }
+
+    private static final ImageTypeProducer [] defaultTypes =
+            new ImageTypeProducer [JPEG.NUM_JCS_CODES];
+
+    public synchronized static ImageTypeProducer getTypeProducer(int csCode) {
+        if (csCode < 0 || csCode >= JPEG.NUM_JCS_CODES) {
+            return null;
+        }
+        if (defaultTypes[csCode] == null) {
+            defaultTypes[csCode] = new ImageTypeProducer(csCode);
+        }
+        return defaultTypes[csCode];
+    }
+
+    protected ImageTypeSpecifier produce() {
+        switch (csCode) {
+            case JPEG.JCS_GRAYSCALE:
+                return ImageTypeSpecifier.createFromBufferedImageType
+                        (BufferedImage.TYPE_BYTE_GRAY);
+            case JPEG.JCS_RGB:
+                return ImageTypeSpecifier.createInterleaved(JPEG.JCS.sRGB,
+                        JPEG.bOffsRGB,
+                        DataBuffer.TYPE_BYTE,
+                        false,
+                        false);
+            case JPEG.JCS_RGBA:
+                return ImageTypeSpecifier.createPacked(JPEG.JCS.sRGB,
+                        0xff000000,
+                        0x00ff0000,
+                        0x0000ff00,
+                        0x000000ff,
+                        DataBuffer.TYPE_INT,
+                        false);
+            case JPEG.JCS_YCC:
+                if (JPEG.JCS.getYCC() != null) {
+                    return ImageTypeSpecifier.createInterleaved(
+                            JPEG.JCS.getYCC(),
+                        JPEG.bandOffsets[2],
+                        DataBuffer.TYPE_BYTE,
+                        false,
+                        false);
+                } else {
+                    return null;
+                }
+            case JPEG.JCS_YCCA:
+                if (JPEG.JCS.getYCC() != null) {
+                    return ImageTypeSpecifier.createInterleaved(
+                            JPEG.JCS.getYCC(),
+                        JPEG.bandOffsets[3],
+                        DataBuffer.TYPE_BYTE,
+                        true,
+                        false);
+                } else {
+                    return null;
+                }
+            default:
+                return null;
+        }
+    }
+}
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 16:55:26 2017 +0200
@@ -812,7 +812,7 @@
                             }
                             break;
                         case ColorSpace.TYPE_3CLR:
-                            if (cs == JPEG.JCS.YCC) {
+                            if (cs == JPEG.JCS.getYCC()) {
                                 if (!alpha) {
                                     if (jfif != null) {
                                         convertTosRGB = true;
@@ -1494,7 +1494,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.JCS.YCC) {
+                if (cs == JPEG.JCS.getYCC()) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1533,7 +1533,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.JCS.YCC) {
+                if (cs == JPEG.JCS.getYCC()) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1579,7 +1579,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.JCS.YCC) {
+                if (cs == JPEG.JCS.getYCC()) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Wed Jul 05 16:55:26 2017 +0200
@@ -490,7 +490,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.JCS.YCC) {
+                if (cs == JPEG.JCS.getYCC()) {
                     wantJFIF = false;
                     componentIDs[0] = (byte) 'Y';
                     componentIDs[1] = (byte) 'C';
--- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java	Wed Jul 05 16:55:26 2017 +0200
@@ -45,6 +45,7 @@
 import java.util.Iterator;
 
 import com.sun.imageio.plugins.common.I18N;
+import com.sun.imageio.plugins.common.ReaderUtil;
 
 /** This class is the Java Image IO plugin reader for WBMP images.
  *  It may subsample the image, clip the image,
@@ -141,11 +142,11 @@
         metadata.wbmpType = wbmpType;
 
         // Read image width
-        width = readMultiByteInteger();
+        width = ReaderUtil.readMultiByteInteger(iis);
         metadata.width = width;
 
         // Read image height
-        height = readMultiByteInteger();
+        height = ReaderUtil.readMultiByteInteger(iis);
         metadata.height = height;
 
         gotHeader = true;
@@ -311,17 +312,6 @@
         gotHeader = false;
     }
 
-    private int readMultiByteInteger() throws IOException {
-        int value = iis.readByte();
-        int result = value & 0x7f;
-        while((value & 0x80) == 0x80) {
-            result <<= 7;
-            value = iis.readByte();
-            result |= (value & 0x7f);
-        }
-        return result;
-    }
-
     /*
      * This method verifies that given byte is valid wbmp type marker.
      * At the moment only 0x0 marker is described by wbmp spec.
--- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Wed Jul 05 16:55:26 2017 +0200
@@ -33,9 +33,13 @@
 import java.io.IOException;
 import javax.imageio.ImageReader;
 import javax.imageio.IIOException;
+import com.sun.imageio.plugins.common.ReaderUtil;
 
 public class WBMPImageReaderSpi extends ImageReaderSpi {
 
+    private static final int MAX_WBMP_WIDTH = 1024;
+    private static final int MAX_WBMP_HEIGHT = 768;
+
     private static String [] writerSpiNames =
         {"com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi"};
     private static String[] formatNames = {"wbmp", "WBMP"};
@@ -79,16 +83,44 @@
         }
 
         ImageInputStream stream = (ImageInputStream)source;
-        byte[] b = new byte[3];
 
         stream.mark();
-        stream.readFully(b);
+        int type = stream.readByte();   // TypeField
+        int fixHeaderField = stream.readByte();
+        // check WBMP "header"
+        if (type != 0 || fixHeaderField != 0) {
+            // while WBMP reader does not support ext WBMP headers
+            stream.reset();
+            return false;
+        }
+
+        int width = ReaderUtil.readMultiByteInteger(stream);
+        int height = ReaderUtil.readMultiByteInteger(stream);
+        // check image dimension
+        if (width <= 0 || height <= 0) {
+            stream.reset();
+            return false;
+        }
+
+        long dataLength = stream.length();
+        if (dataLength == -1) {
+            // We can't verify that amount of data in the stream
+            // corresponds to image dimension because we do not know
+            // the length of the data stream.
+            // Assuming that wbmp image are used for mobile devices,
+            // let's introduce an upper limit for image dimension.
+            // In case if exact amount of raster data is unknown,
+            // let's reject images with dimension above the limit.
+            stream.reset();
+            return (width < MAX_WBMP_WIDTH) && (height < MAX_WBMP_HEIGHT);
+        }
+
+        dataLength -= stream.getStreamPosition();
         stream.reset();
 
-        return ((b[0] == (byte)0) &&  // TypeField == 0
-                b[1] == 0 && // FixHeaderField == 0xxx00000; not support ext header
-                ((b[2] & 0x8f) != 0 || (b[2] & 0x7f) != 0));  // First width byte
-                //XXX: b[2] & 0x8f) != 0 for the bug in Sony Ericsson encoder.
+        long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1);
+
+        return (dataLength == scanSize * height);
     }
 
     public ImageReader createReaderInstance(Object extension)
--- a/jdk/src/share/classes/java/awt/Font.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/java/awt/Font.java	Wed Jul 05 16:55:26 2017 +0200
@@ -445,18 +445,19 @@
      */
     private AttributeValues getAttributeValues() {
         if (values == null) {
-            values = new AttributeValues();
-            values.setFamily(name);
-            values.setSize(pointSize); // expects the float value.
+            AttributeValues valuesTmp = new AttributeValues();
+            valuesTmp.setFamily(name);
+            valuesTmp.setSize(pointSize); // expects the float value.
 
             if ((style & BOLD) != 0) {
-                values.setWeight(2); // WEIGHT_BOLD
+                valuesTmp.setWeight(2); // WEIGHT_BOLD
             }
 
             if ((style & ITALIC) != 0) {
-                values.setPosture(.2f); // POSTURE_OBLIQUE
+                valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
             }
-            values.defineAll(PRIMARY_MASK); // for streaming compatibility
+            valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
+            values = valuesTmp;
         }
 
         return values;
--- a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Wed Jul 05 16:55:26 2017 +0200
@@ -79,8 +79,9 @@
 
             try {
 //                      long t0 = System.currentTimeMillis();
-                localEnv =
-                    (GraphicsEnvironment) Class.forName(nm).newInstance();
+                ClassLoader cl = ClassLoader.getSystemClassLoader();
+                Class geCls = Class.forName(nm, true, cl);
+                localEnv = (GraphicsEnvironment)geCls.newInstance();
 //              long t1 = System.currentTimeMillis();
 //              System.out.println("GE creation took " + (t1-t0)+ "ms.");
                 if (isHeadless()) {
--- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 05 16:55:26 2017 +0200
@@ -863,11 +863,16 @@
         case ColorSpace.CS_PYCC:
             synchronized(ICC_Profile.class) {
                 if (PYCCprofile == null) {
-                    ProfileDeferralInfo pInfo =
-                        new ProfileDeferralInfo("PYCC.pf",
-                                                ColorSpace.TYPE_3CLR, 3,
-                                                CLASS_DISPLAY);
-                    PYCCprofile = getDeferredInstance(pInfo);
+                    if (getProfileFile("PYCC.pf") != null) {
+                        ProfileDeferralInfo pInfo =
+                            new ProfileDeferralInfo("PYCC.pf",
+                                                    ColorSpace.TYPE_3CLR, 3,
+                                                    CLASS_DISPLAY);
+                        PYCCprofile = getDeferredInstance(pInfo);
+                    } else {
+                        throw new IllegalArgumentException(
+                                "Can't load standard profile: PYCC.pf");
+                    }
                 }
                 thisProfile = PYCCprofile;
             }
@@ -1783,17 +1788,33 @@
         return (FileInputStream)java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction() {
             public Object run() {
-                return privilegedOpenProfile(fileName);
+                File f = privilegedGetProfileFile(fileName);
+                if (f != null) {
+                    try {
+                        return new FileInputStream(f);
+                    } catch (FileNotFoundException e) {
+                    }
+                }
+                return null;
+            }
+        });
+    }
+
+    private static File getProfileFile(final String fileName) {
+        return (File)java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction() {
+            public Object run() {
+                return privilegedGetProfileFile(fileName);
             }
         });
     }
 
     /*
-     * this version is called from doPrivileged in privilegedOpenProfile.
-     * the whole method is privileged!
+     * this version is called from doPrivileged in openProfile
+     * or getProfileFile, so the whole method is privileged!
      */
-    private static FileInputStream privilegedOpenProfile(String fileName) {
-        FileInputStream fis = null;
+
+    private static File privilegedGetProfileFile(String fileName) {
         String path, dir, fullPath;
 
         File f = new File(fileName); /* try absolute file name */
@@ -1830,12 +1851,9 @@
             }
 
         if (f.isFile()) {
-            try {
-                fis = new FileInputStream(f);
-            } catch (FileNotFoundException e) {
-            }
+            return f;
         }
-        return fis;
+        return null;
     }
 
 
--- a/jdk/src/share/classes/javax/imageio/ImageIO.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/javax/imageio/ImageIO.java	Wed Jul 05 16:55:26 2017 +0200
@@ -28,6 +28,7 @@
 import java.awt.image.BufferedImage;
 import java.awt.image.RenderedImage;
 import java.io.File;
+import java.io.FilePermission;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -195,13 +196,22 @@
                     } else {
                         cachepath = getTempDir();
 
-                        if (cachepath == null) {
+                        if (cachepath == null || cachepath.isEmpty()) {
                             getCacheInfo().setHasPermission(Boolean.FALSE);
                             return false;
                         }
                     }
 
-                    security.checkWrite(cachepath);
+                    // we have to check whether we can read, write,
+                    // and delete cache files.
+                    // So, compose cache file path and check it.
+                    String filepath = cachepath;
+                    if (!filepath.endsWith(File.separator)) {
+                        filepath += File.separator;
+                    }
+                    filepath += "*";
+
+                    security.checkPermission(new FilePermission(filepath, "read, write, delete"));
                 }
             } catch (SecurityException e) {
                 getCacheInfo().setHasPermission(Boolean.FALSE);
--- a/jdk/src/share/classes/sun/font/TrueTypeFont.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/sun/font/TrueTypeFont.java	Wed Jul 05 16:55:26 2017 +0200
@@ -160,6 +160,13 @@
     private boolean supportsJA;
     private boolean supportsCJK;
 
+    /* These are for faster access to the name of the font as
+     * typically exposed via API to applications.
+     */
+    private Locale nameLocale;
+    private String localeFamilyName;
+    private String localeFullName;
+
     /**
      * - does basic verification of the file
      * - reads the header table for this font (within a collection)
@@ -1092,6 +1099,10 @@
              * greater than 32767, so read and store those as ints
              */
             int stringPtr = sbuffer.get() & 0xffff;
+
+            nameLocale = sun.awt.SunToolkit.getStartupLocale();
+            short nameLocaleID = FontManager.getLCIDFromLocale(nameLocale);
+
             for (int i=0; i<numRecords; i++) {
                 short platformID = sbuffer.get();
                 if (platformID != MS_PLATFORM_ID) {
@@ -1103,15 +1114,24 @@
                 short nameID     = sbuffer.get();
                 int nameLen    = ((int) sbuffer.get()) & 0xffff;
                 int namePtr    = (((int) sbuffer.get()) & 0xffff) + stringPtr;
-
+                String tmpName = null;
                 switch (nameID) {
 
                 case FAMILY_NAME_ID:
 
-                    if (familyName == null || langID == ENGLISH_LOCALE_ID) {
+                    if (familyName == null || langID == ENGLISH_LOCALE_ID ||
+                        langID == nameLocaleID)
+                    {
                         buffer.position(namePtr);
                         buffer.get(name, 0, nameLen);
-                        familyName = makeString(name, nameLen, encodingID);
+                        tmpName = makeString(name, nameLen, encodingID);
+
+                        if (familyName == null || langID == ENGLISH_LOCALE_ID){
+                            familyName = tmpName;
+                        }
+                        if (langID == nameLocaleID) {
+                            localeFamilyName = tmpName;
+                        }
                     }
 /*
                     for (int ii=0;ii<nameLen;ii++) {
@@ -1129,15 +1149,29 @@
 
                 case FULL_NAME_ID:
 
-                    if (fullName == null || langID == ENGLISH_LOCALE_ID) {
+                    if (fullName == null || langID == ENGLISH_LOCALE_ID ||
+                        langID == nameLocaleID)
+                    {
                         buffer.position(namePtr);
                         buffer.get(name, 0, nameLen);
-                        fullName = makeString(name, nameLen, encodingID);
+                        tmpName = makeString(name, nameLen, encodingID);
+
+                        if (fullName == null || langID == ENGLISH_LOCALE_ID) {
+                            fullName = tmpName;
+                        }
+                        if (langID == nameLocaleID) {
+                            localeFullName = tmpName;
+                        }
                     }
                     break;
-
                 }
             }
+            if (localeFamilyName == null) {
+                localeFamilyName = familyName;
+            }
+            if (localeFullName == null) {
+                localeFullName = fullName;
+            }
         }
     }
 
@@ -1220,6 +1254,8 @@
     public String getFontName(Locale locale) {
         if (locale == null) {
             return fullName;
+        } else if (locale.equals(nameLocale) && localeFullName != null) {
+            return localeFullName;
         } else {
             short localeID = FontManager.getLCIDFromLocale(locale);
             String name = lookupName(localeID, FULL_NAME_ID);
@@ -1234,11 +1270,13 @@
     public String getFamilyName(Locale locale) {
         if (locale == null) {
             return familyName;
+        } else if (locale.equals(nameLocale) && localeFamilyName != null) {
+            return localeFamilyName;
         } else {
             short localeID = FontManager.getLCIDFromLocale(locale);
             String name = lookupName(localeID, FAMILY_NAME_ID);
             if (name == null) {
-                return familyName;
+               return familyName;
             } else {
                 return name;
             }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Wed Jul 05 16:55:26 2017 +0200
@@ -96,7 +96,7 @@
             bboxX1 = x1+1;
         } else {
             if (bboxX0 > x0) bboxX0 = x0;
-            if (bboxX1 < x1) bboxX1 = x1;
+            if (bboxX1 < x1 + 1) bboxX1 = x1 + 1;
             while (bboxY1++ < y) {
                 reallocRowInfo(alphaRows+1);
                 minTouched[alphaRows] = 0;
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 16:55:03 2017 +0200
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 16:55:26 2017 +0200
@@ -1783,7 +1783,7 @@
 
 
     struct jpeg_source_mgr *src;
-    JSAMPROW scanLinePtr;
+    JSAMPROW scanLinePtr = NULL;
     jint bands[MAX_BANDS];
     int i, j;
     jint *body;
@@ -1819,7 +1819,7 @@
 
     cinfo = (j_decompress_ptr) data->jpegObj;
 
-    if ((numBands < 1) || (numBands > cinfo->num_components) ||
+    if ((numBands < 1) ||
         (sourceXStart < 0) || (sourceXStart >= (jint)cinfo->image_width) ||
         (sourceYStart < 0) || (sourceYStart >= (jint)cinfo->image_height) ||
         (sourceWidth < 1) || (sourceWidth > (jint)cinfo->image_width) ||
@@ -1877,16 +1877,6 @@
         return data->abortFlag;  // We already threw an out of memory exception
     }
 
-    // Allocate a 1-scanline buffer
-    scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->num_components);
-    if (scanLinePtr == NULL) {
-        RELEASE_ARRAYS(env, data, src->next_input_byte);
-        JNU_ThrowByName( env,
-                         "java/lang/OutOfMemoryError",
-                         "Reading JPEG Stream");
-        return data->abortFlag;
-    }
-
     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
     jerr = (sun_jpeg_error_ptr) cinfo->err;
 
@@ -1900,7 +1890,10 @@
                                           buffer);
             JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
         }
-        free(scanLinePtr);
+        if (scanLinePtr != NULL) {
+            free(scanLinePtr);
+            scanLinePtr = NULL;
+        }
         return data->abortFlag;
     }
 
@@ -1938,6 +1931,23 @@
 
     jpeg_start_decompress(cinfo);
 
+    if (numBands !=  cinfo->output_components) {
+        JNU_ThrowByName(env, "javax/imageio/IIOException",
+                        "Invalid argument to native readImage");
+        return data->abortFlag;
+    }
+
+
+    // Allocate a 1-scanline buffer
+    scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components);
+    if (scanLinePtr == NULL) {
+        RELEASE_ARRAYS(env, data, src->next_input_byte);
+        JNU_ThrowByName( env,
+                         "java/lang/OutOfMemoryError",
+                         "Reading JPEG Stream");
+        return data->abortFlag;
+    }
+
     // loop over progressive passes
     done = FALSE;
     while (!done) {
@@ -1965,9 +1975,9 @@
 
         scanlineLimit = sourceYStart+sourceHeight;
         pixelLimit = scanLinePtr
-            +(sourceXStart+sourceWidth)*cinfo->num_components;
-
-        pixelStride = stepX*cinfo->num_components;
+            +(sourceXStart+sourceWidth)*cinfo->output_components;
+
+        pixelStride = stepX*cinfo->output_components;
         targetLine = 0;
 
         while ((data->abortFlag == JNI_FALSE)
@@ -1982,12 +1992,12 @@
                 // Optimization: The component bands are ordered sequentially,
                 // so we can simply use memcpy() to copy the intermediate
                 // scanline buffer into the raster.
-                in = scanLinePtr + (sourceXStart * cinfo->num_components);
+                in = scanLinePtr + (sourceXStart * cinfo->output_components);
                 if (pixelLimit > in) {
                     memcpy(out, in, pixelLimit - in);
                 }
             } else {
-                for (in = scanLinePtr+sourceXStart*cinfo->num_components;
+                for (in = scanLinePtr+sourceXStart*cinfo->output_components;
                      in < pixelLimit;
                      in += pixelStride) {
                     for (i = 0; i < numBands; i++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * 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     6684104
+ * @summary Test verifies that ImageIO checks all permissions required for
+ *           the file cache usage:
+ *
+ *          no policy file: No security restrictions.
+ *             Expected result: ImageIO creates file-cached stream.
+ *
+ *          w.policy: the case when we have read and write permissions
+ *              for java.io.temp directory but have only write permission
+ *              for a temp file.
+ *             Expected result: ImageIO create a memory-cached stream
+ *              image output stream.
+ *
+ *          rw.policy: the case when we  have read and write permissions
+ *              for java.io.temp directory but have only read and write
+ *              permission for a temp cache file.
+ *             Expected result: ImageIO creates a memory-cached stream
+ *              because temporary cache file can not be deleted.
+ *
+ *          rwd.policy: the case when we  have read and write permissions
+ *              for java.io.temp directory and have all required permissions
+ *             (read, write, and delete) for a temporary cache file.
+ *             Expected result: ImageIO creates file-cached stream.
+ *
+ *           -Djava.security.debug=access can be used to verify file permissions.
+ *
+ * @run     main CachePermissionsTest true
+ * @run     main/othervm/policy=w.policy CachePermissionsTest false
+ * @run     main/othervm/policy=rw.policy CachePermissionsTest false
+ * @run     main/othervm/policy=rwd.policy CachePermissionsTest true
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import javax.imageio.stream.ImageOutputStream;
+
+import javax.imageio.ImageIO;
+
+
+public class CachePermissionsTest {
+    public static void main(String[] args) {
+        boolean isFileCacheExpected =
+            Boolean.valueOf(args[0]).booleanValue();
+        System.out.println("Is file cache expected: " + isFileCacheExpected);
+
+        ImageIO.setUseCache(true);
+
+        System.out.println("java.io.tmpdir is " + System.getProperty("java.io.tmpdir"));
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        try {
+            ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
+
+            boolean isFileCache = ios.isCachedFile();
+            System.out.println("Is file cache used: " + isFileCache);
+
+            if (isFileCache !=isFileCacheExpected) {
+                System.out.println("WARNING: file chace usage is not as expected!");
+            }
+
+            System.out.println("Verify data writing...");
+            for (int i = 0; i < 8192; i++) {
+                ios.writeInt(i);
+            }
+
+            System.out.println("Verify data reading...");
+            ios.seek(0L);
+
+            for (int i = 0; i < 8192; i++) {
+                int j = ios.readInt();
+                if (i != j) {
+                    throw new RuntimeException("Wrong data in the stream " + j + " instead of " + i);
+                }
+            }
+
+            System.out.println("Verify stream closing...");
+            ios.close();
+        } catch (IOException e) {
+            /*
+             * Something went wrong?
+             */
+            throw new RuntimeException("Test FAILED.", e);
+        } catch (SecurityException e) {
+            /*
+             * We do not expect security execptions here:
+             * we there are any security restrition, ImageIO
+             * should swith to memory-cached streams, instead
+             * of using file cache.
+             */
+            throw new RuntimeException("Test FAILED.", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/CachePremissionsTest/rw.policy	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,5 @@
+grant {
+      permission java.util.PropertyPermission "test.classes", "read";
+      permission java.util.PropertyPermission "java.io.tmpdir", "read";
+      permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/CachePremissionsTest/rwd.policy	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,5 @@
+grant {
+      permission java.util.PropertyPermission "test.classes", "read";
+      permission java.util.PropertyPermission "java.io.tmpdir", "read";
+      permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write, delete";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/CachePremissionsTest/w.policy	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,5 @@
+grant {
+      permission java.util.PropertyPermission "test.classes", "read";
+      permission java.util.PropertyPermission "java.io.tmpdir", "read";
+      permission java.io.FilePermission "${java.io.tmpdir}${/}*", "write";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/bmp/TopDownTest.java	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * 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     6296893
+ * @summary Test verifies that the isTopDown flag does not cause
+ *          a writing of bmp image in wrong scanline layout.
+ * @run     main TopDownTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+import java.awt.image.IndexColorModel;
+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.plugins.bmp.BMPImageWriteParam;
+import javax.imageio.stream.ImageOutputStream;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+
+public class TopDownTest {
+
+    public static void main(String[] args) throws IOException {
+        BufferedImage src = createTestImage(24);
+
+        writeWithCompression(src, "BI_BITFIELDS");
+
+        writeWithCompression(src, "BI_RGB");
+
+        src = createTestImage(8);
+        writeWithCompression(src, "BI_RLE8");
+
+        src = createTestImage(4);
+        writeWithCompression(src, "BI_RLE4");
+
+    }
+
+    private static void writeWithCompression(BufferedImage src,
+                                             String compression) throws IOException
+    {
+        System.out.println("Compression: " + compression);
+        ImageWriter writer = ImageIO.getImageWritersByFormatName("BMP").next();
+        if (writer == null) {
+            throw new RuntimeException("Test failed: no bmp writer available");
+        }
+        File fout = File.createTempFile(compression + "_", ".bmp",
+                                        new File("."));
+
+        ImageOutputStream ios = ImageIO.createImageOutputStream(fout);
+        writer.setOutput(ios);
+
+        BMPImageWriteParam param = (BMPImageWriteParam)
+                writer.getDefaultWriteParam();
+        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+        param.setCompressionType(compression);
+        param.setTopDown(true);
+        writer.write(null, new IIOImage(src, null, null), param);
+        writer.dispose();
+        ios.flush();
+        ios.close();
+
+        BufferedImage dst = ImageIO.read(fout);
+
+        verify(dst);
+    }
+
+    private static void verify(BufferedImage dst) {
+        int top_rgb = dst.getRGB(50, 25);
+        System.out.printf("top_rgb: %x\n", top_rgb);
+        int bot_rgb = dst.getRGB(50, 75);
+        System.out.printf("bot_rgb: %x\n", bot_rgb);
+
+        // expect to see blue color on the top of image
+        if (top_rgb != 0xff0000ff) {
+            throw new RuntimeException("Invaid top color: " +
+                        Integer.toHexString(bot_rgb));
+        }
+        if (bot_rgb != 0xffff0000) {
+            throw new RuntimeException("Invalid bottom color: " +
+                    Integer.toHexString(bot_rgb));
+        }
+    }
+
+    private static BufferedImage createTestImage(int bpp) {
+
+        BufferedImage img = null;
+        switch (bpp) {
+            case 8:
+                img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED);
+                break;
+            case 4: {
+                byte[] r = new byte[16];
+                byte[] g = new byte[16];
+                byte[] b = new byte[16];
+
+                r[1] = (byte)0xff;
+                b[0] = (byte)0xff;
+
+                IndexColorModel icm = new IndexColorModel(4, 16, r, g, b);
+                img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED, icm);
+                }
+                break;
+            case 24:
+            default:
+            img = new BufferedImage(100, 100, TYPE_INT_RGB);
+        }
+        Graphics g = img.createGraphics();
+        g.setColor(Color.blue);
+        g.fillRect(0, 0, 100, 50);
+        g.setColor(Color.red);
+        g.fillRect(0, 50, 100, 50);
+        g.dispose();
+        return img;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,179 @@
+/*
+ * 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     4893408
+ *
+ * @summary Test verifies that Image I/O jpeg reader correctly handles
+ *          destination types if number of color components in destination
+ *          differs from number of color components in the jpeg image.
+ *          Particularly, it verifies reading YCbCr image as a grayscaled
+ *          and reading grayscaled jpeg as a RGB.
+ *
+ * @run     main ReadAsGrayTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.stream.ImageInputStream;
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY;
+import static java.awt.color.ColorSpace.TYPE_GRAY;
+import static java.awt.color.ColorSpace.CS_sRGB;
+
+public class ReadAsGrayTest {
+    static Color[] colors = new Color[] {
+        Color.white, Color.red, Color.green,
+        Color.blue, Color.black };
+
+    static final int dx = 50;
+    static final int h = 100;
+
+    static ColorSpace sRGB = ColorSpace.getInstance(CS_sRGB);
+
+
+    public static void main(String[] args) throws IOException {
+        System.out.println("Type TYPE_BYTE_GRAY");
+        doTest(TYPE_BYTE_GRAY);
+
+        System.out.println("Type TYPE_3BYTE_BGR");
+        doTest(TYPE_3BYTE_BGR);
+
+        System.out.println("Test PASSED.");
+    }
+
+    private static void doTest(int type) throws IOException {
+        BufferedImage src = createTestImage(type);
+
+        File f = new File("test.jpg");
+
+        if (!ImageIO.write(src, "jpg", f)) {
+            throw new RuntimeException("Failed to write test image.");
+        }
+
+        ImageInputStream iis = ImageIO.createImageInputStream(f);
+        ImageReader reader = ImageIO.getImageReaders(iis).next();
+        reader.setInput(iis);
+
+        Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
+        ImageTypeSpecifier srgb = null;
+        ImageTypeSpecifier gray = null;
+        // look for gray and srgb types
+        while ((srgb == null || gray == null) && types.hasNext()) {
+            ImageTypeSpecifier t = types.next();
+            if (t.getColorModel().getColorSpace().getType() == TYPE_GRAY) {
+                gray = t;
+            }
+            if (t.getColorModel().getColorSpace() == sRGB) {
+                srgb = t;
+            }
+        }
+        if (gray == null) {
+            throw new RuntimeException("No gray type available.");
+        }
+        if (srgb == null) {
+            throw new RuntimeException("No srgb type available.");
+        }
+
+        System.out.println("Read as GRAY...");
+        testType(reader, gray, src);
+
+        System.out.println("Read as sRGB...");
+        testType(reader, srgb, src);
+    }
+
+    private static void testType(ImageReader reader,
+                                 ImageTypeSpecifier t,
+                                 BufferedImage src)
+        throws IOException
+    {
+        ImageReadParam p = reader.getDefaultReadParam();
+        p.setDestinationType(t);
+        BufferedImage dst = reader.read(0, p);
+
+        verify(src, dst, t);
+    }
+
+    private static void verify(BufferedImage src,
+                               BufferedImage dst,
+                               ImageTypeSpecifier type)
+    {
+        BufferedImage test =
+                type.createBufferedImage(src.getWidth(), src.getHeight());
+        Graphics2D g = test.createGraphics();
+        g.drawImage(src, 0, 0, null);
+        g.dispose();
+
+        for (int i = 0; i < colors.length; i++) {
+            int x = i * dx + dx / 2;
+            int y = h / 2;
+
+            Color c_test = new Color(test.getRGB(x, y));
+            Color c_dst = new Color(dst.getRGB(x, y));
+
+            if (!compareWithTolerance(c_test, c_dst, 0.01f)) {
+                String msg = String.format("Invalid color: %x instead of %x",
+                                           c_dst.getRGB(), c_test.getRGB());
+                throw new RuntimeException("Test failed: " + msg);
+            }
+        }
+        System.out.println("Verified.");
+    }
+
+    private static boolean compareWithTolerance(Color a, Color b, float delta) {
+        float[] a_rgb = new float[3];
+        a_rgb = a.getRGBColorComponents(a_rgb);
+        float[] b_rgb = new float[3];
+        b_rgb = b.getRGBColorComponents(b_rgb);
+
+        for (int i = 0; i < 3; i++) {
+            if (Math.abs(a_rgb[i] - b_rgb[i]) > delta) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static BufferedImage createTestImage(int type) {
+        BufferedImage img = new BufferedImage(dx * colors.length, h, type);
+
+        Graphics2D g = img.createGraphics();
+        for (int i = 0; i < colors.length; i++) {
+            g.setColor(colors[i]);
+            g.fillRect(i * dx, 0, dx, h);
+        }
+        g.dispose();
+
+        return img;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,131 @@
+/*
+ * 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     5101862
+ * @summary Test verifies that SPI of WBMP image reader
+ *           does not claims to be able to decode QT movies,
+ *           tga images, or ico files.
+ * @run     main CanDecodeTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Vector;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+public class CanDecodeTest {
+
+    public static void main(String[] args) throws IOException {
+        ImageReader r =
+                ImageIO.getImageReadersByFormatName("WBMP").next();
+        ImageReaderSpi spi = r.getOriginatingProvider();
+
+        Vector<TestCase> tests = getTestCases();
+        for (TestCase t : tests) {
+            t.doTest(spi);
+        }
+        System.out.println("Test passed.");
+    }
+
+    private static Vector<TestCase> getTestCases() {
+        Vector<TestCase> v = new Vector<TestCase>(4);
+        v.add(new TestCase("wbmp", new byte[]{(byte) 0x00, (byte) 0x00,
+                    (byte) 0x60, (byte) 0x14}, 244, true));
+        v.add(new TestCase("mov", new byte[]{(byte) 0x00, (byte) 0x00,
+                    (byte) 0x07, (byte) 0xb5, (byte) 0x6d}, 82397, false));
+        v.add(new TestCase("tga", new byte[]{(byte) 0x00, (byte) 0x00,
+                    (byte) 0x0a, (byte) 0x00}, 39693, false));
+        v.add(new TestCase("ico", new byte[]{(byte) 0x00, (byte) 0x00,
+                    (byte) 0x01, (byte) 0x00}, 1078, false));
+        return v;
+    }
+
+    private static class TestCase {
+
+        private String title;
+        private byte[] header;
+        private int dataLength;
+        private boolean canDecode;
+
+        public TestCase(String title, byte[] header,
+                int dataLength, boolean canDecode) {
+            this.title = title;
+            this.dataLength = dataLength;
+            this.header = header.clone();
+            this.canDecode = canDecode;
+
+        }
+
+        public void doTest(ImageReaderSpi spi) throws IOException {
+            System.out.println("Test for " + title +
+                    (canDecode ? " (can decode)" : " (can't decode)"));
+            System.out.print("As a stream...");
+            ImageInputStream iis =
+                    ImageIO.createImageInputStream(getDataStream());
+
+            if (spi.canDecodeInput(iis) != canDecode) {
+                throw new RuntimeException("Test failed: wrong decideion " +
+                        "for stream data");
+            }
+            System.out.println("OK");
+
+            System.out.print("As a file...");
+            iis = ImageIO.createImageInputStream(getDataFile());
+            if (spi.canDecodeInput(iis) != canDecode) {
+                throw new RuntimeException("Test failed: wrong decideion " +
+                        "for file data");
+            }
+            System.out.println("OK");
+        }
+
+        private byte[] getData() {
+            byte[] data = new byte[dataLength];
+            Arrays.fill(data, (byte) 0);
+            System.arraycopy(header, 0, data, 0, header.length);
+
+            return data;
+        }
+        public InputStream getDataStream() {
+            return new ByteArrayInputStream(getData());
+        }
+
+        public File getDataFile() throws IOException {
+            File f = File.createTempFile("wbmp_", "." + title, new File("."));
+            FileOutputStream fos = new FileOutputStream(f);
+            fos.write(getData());
+            fos.flush();
+            fos.close();
+
+            return f;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/pisces/ScaleTest.java	Wed Jul 05 16:55:26 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import javax.imageio.ImageIO;
+
+
+public class ScaleTest {
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+    g.scale(.9, .9);
+    g.setPaint(Color.BLACK);
+    g.setStroke(new BasicStroke(0.5f));
+    g.draw(new Ellipse2D.Double(25, 25, 150, 150));
+
+    // To visually check it
+    //ImageIO.write(image, "PNG", new File(args[0]));
+
+    boolean nonWhitePixelFound = false;
+    for (int x = 100; x < 200; ++x) {
+      if (image.getRGB(x, 90) != Color.WHITE.getRGB()) {
+        nonWhitePixelFound = true;
+        break;
+      }
+    }
+    if (!nonWhitePixelFound) {
+      throw new RuntimeException("A circle is rendered like a 'C' shape.");
+    }
+  }
+}
--- a/langtools/.hgtags	Wed Jul 05 16:55:03 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 16:55:26 2017 +0200
@@ -36,3 +36,4 @@
 88bcb6772159602317f2e184a69010737db72270 jdk7-b59
 5cdce469ea2ad90d308c9abe420fd0643c0a6b9e jdk7-b60
 522520757dd34321b27a7145ecbd24ac4fb64f34 jdk7-b61
+6855e5aa3348f185fe5b443ee43a1b00ec5d390e jdk7-b62