Merge
authorduke
Wed, 05 Jul 2017 16:55:23 +0200
changeset 3026 0910b6a4bf35
parent 3025 7f19175c3da7 (current diff)
parent 3024 6891b9cdc4f7 (diff)
child 3028 9136c5aa1be9
Merge
--- a/.hgtags-top-repo	Thu Jun 25 12:09:54 2009 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 16:55:23 2017 +0200
@@ -36,3 +36,4 @@
 030142474602b4a067662fffc0c8e541de5a78df jdk7-b59
 39565502682c7085369bd09e51640919dc741097 jdk7-b60
 472c21584cfd7e9c0229ad6a100366a5c03d2976 jdk7-b61
+c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62
--- a/corba/.hgtags	Thu Jun 25 12:09:54 2009 -0700
+++ b/corba/.hgtags	Wed Jul 05 16:55:23 2017 +0200
@@ -36,3 +36,4 @@
 7e6b2b55c00cc523b468272353ada3979adbbf16 jdk7-b59
 f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60
 e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61
+65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62
--- a/hotspot/.hgtags	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 16:55:23 2017 +0200
@@ -36,3 +36,4 @@
 c55be0c7bd32c016c52218eb4c8b5da8a75450b5 jdk7-b59
 a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60
 27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61
+a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62
--- a/hotspot/make/hotspot_version	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/make/hotspot_version	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler1	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/memory/gcLocker.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/hotspot/src/share/vm/utilities/macros.hpp	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 16:55:23 2017 +0200
@@ -36,3 +36,4 @@
 75113d7ce083048e7576b9d0d60a4e80db6b181f jdk7-b59
 259aef5045a155eb6a2f8dd0e2429c6dbe0f652f jdk7-b60
 f1ac756616eaaad795f77f7f5e7f7c7bfdc9c1de jdk7-b61
+a97dd57a62604c35c79bc2fa77a612ed547f6135 jdk7-b62
--- a/jdk/.hgtags	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/.hgtags	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/java/awt/Font.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/javax/imageio/ImageIO.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/sun/font/TrueTypeFont.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Wed Jul 05 16:55:23 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	Thu Jun 25 12:09:54 2009 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 16:55:23 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:23 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:23 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:23 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:23 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:23 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:23 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:23 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:23 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.");
+    }
+  }
+}