Merge
This commit is contained in:
commit
9da28758ff
@ -36,3 +36,4 @@ ffd09e767dfa6d21466183a400f72cf62d53297f jdk7-b57
|
||||
030142474602b4a067662fffc0c8e541de5a78df jdk7-b59
|
||||
39565502682c7085369bd09e51640919dc741097 jdk7-b60
|
||||
472c21584cfd7e9c0229ad6a100366a5c03d2976 jdk7-b61
|
||||
c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62
|
||||
|
@ -36,3 +36,4 @@ bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52
|
||||
7e6b2b55c00cc523b468272353ada3979adbbf16 jdk7-b59
|
||||
f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60
|
||||
e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61
|
||||
65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62
|
||||
|
@ -36,3 +36,4 @@ f4cbf78110c726919f46b59a3b054c54c7e889b4 jdk7-b57
|
||||
c55be0c7bd32c016c52218eb4c8b5da8a75450b5 jdk7-b59
|
||||
a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60
|
||||
27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61
|
||||
a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||
|
||||
HS_MAJOR_VER=16
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=04
|
||||
HS_BUILD_NUMBER=05
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=7
|
||||
|
@ -1157,6 +1157,13 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
|
||||
} 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 @@ void ConcurrentMark::cleanup() {
|
||||
// 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() {
|
||||
|
@ -1535,6 +1535,15 @@ jint G1CollectedHeap::initialize() {
|
||||
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 @@ public:
|
||||
};
|
||||
|
||||
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 @@ public:
|
||||
};
|
||||
|
||||
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(¬_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 @@ class VerifyRootsClosure: public OopsInGenClosure {
|
||||
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 @@ public:
|
||||
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 @@ class G1ParVerifyTask: public AbstractGangTask {
|
||||
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 @@ void G1CollectedHeap::verify(bool allow_dirty, bool silent) {
|
||||
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 @@ void G1CollectedHeap::verify(bool allow_dirty, bool silent) {
|
||||
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 ");
|
||||
|
@ -59,6 +59,9 @@ class ConcurrentZFThread;
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
// 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 @@ public:
|
||||
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;
|
||||
|
@ -40,15 +40,19 @@ FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r,
|
||||
{}
|
||||
|
||||
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 @@ public:
|
||||
|
||||
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 @@ void HeapRegion::print_on(outputStream* st) const {
|
||||
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 @@ void HeapRegion::verify(bool allow_dirty) const {
|
||||
}
|
||||
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);
|
||||
|
@ -782,7 +782,16 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
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
|
||||
|
@ -109,7 +109,7 @@ protected:
|
||||
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 @@ protected:
|
||||
// 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 @@ public:
|
||||
#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 @@ void OtherRegionsTable::add_reference(oop* from, int tid) {
|
||||
|
||||
// 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 @@ void OtherRegionsTable::add_reference(oop* from, int tid) {
|
||||
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 @@ void OtherRegionsTable::add_reference(oop* from, int tid) {
|
||||
}
|
||||
|
||||
// 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 @@ void OtherRegionsTable::add_reference(oop* from, int tid) {
|
||||
// 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(oop* from) const {
|
||||
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 @@ bool OtherRegionsTable::contains_reference_locked(oop* from) const {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) {
|
||||
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 @@ void SparsePRTEntry::init(short region_ind) {
|
||||
_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 @@ int SparsePRTEntry::num_valid_cards() const {
|
||||
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 @@ SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(short card_index) {
|
||||
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 @@ RSHashTable::RSHashTable(size_t capacity) :
|
||||
_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 @@ RSHashTable::~RSHashTable() {
|
||||
_entries = NULL;
|
||||
}
|
||||
if (_buckets != NULL) {
|
||||
FREE_C_HEAP_ARRAY(short, _buckets);
|
||||
FREE_C_HEAP_ARRAY(int, _buckets);
|
||||
_buckets = NULL;
|
||||
}
|
||||
}
|
||||
@ -153,14 +157,18 @@ void RSHashTable::clear() {
|
||||
_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 @@ bool RSHashTable::add_card(short region_ind, short card_index) {
|
||||
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 @@ bool RSHashTable::get_cards(short region_ind, short* cards) {
|
||||
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 @@ bool RSHashTable::delete_entry(short region_ind) {
|
||||
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(short region_ind) const {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ SparsePRTEntry* RSHashTable::entry_for_region_ind_create(short region_ind) {
|
||||
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 @@ short RSHashTable::alloc_entry() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 @@ RSHashTable* RSHashTable::get_from_deleted_list() {
|
||||
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 @@ short /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
|
||||
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 @@ size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(short ci) {
|
||||
|
||||
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 @@ bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
|
||||
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 @@ void SparsePRT::add_to_expanded_list(SparsePRT* sprt) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SparsePRT* SparsePRT::get_from_expanded_list() {
|
||||
SparsePRT* hd = _head_expanded_list;
|
||||
while (hd != NULL) {
|
||||
@ -452,6 +461,7 @@ SparsePRT::SparsePRT(HeapRegion* hr) :
|
||||
_next = _cur;
|
||||
}
|
||||
|
||||
|
||||
SparsePRT::~SparsePRT() {
|
||||
assert(_next != NULL && _cur != NULL, "Inv");
|
||||
if (_cur != _next) { delete _cur; }
|
||||
@ -465,7 +475,7 @@ size_t SparsePRT::mem_size() const {
|
||||
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 @@ bool SparsePRT::add_card(short region_id, short card_index) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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 @@ public:
|
||||
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 @@ class RSHashTable : public CHeapObj {
|
||||
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 @@ class RSHashTable : public CHeapObj {
|
||||
// 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 @@ public:
|
||||
// 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,52 +162,50 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
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::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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool has_next(size_t& card_index);
|
||||
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
|
||||
};
|
||||
|
||||
// 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();
|
||||
|
||||
// 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)
|
||||
{}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
// Concurrent accesss to a SparsePRT must be serialized by some external
|
||||
// mutex.
|
||||
|
||||
@ -238,7 +236,6 @@ class SparsePRT VALUE_OBJ_CLASS_SPEC {
|
||||
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 @@ public:
|
||||
// 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 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,6 @@ concurrentG1Refine.hpp globalDefinitions.hpp
|
||||
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.cpp space.inline.hpp
|
||||
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
|
||||
|
||||
|
@ -177,6 +177,7 @@ private:
|
||||
// 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 bool ParMarkBitMap::is_unmarked(oop obj) const
|
||||
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
|
||||
|
@ -387,7 +387,7 @@ c1_ValueMap.hpp c1_ValueSet.hpp
|
||||
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
|
||||
|
@ -242,6 +242,31 @@ class Pause_No_Safepoint_Verifier : public Pause_No_GC_Verifier {
|
||||
#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
|
||||
|
@ -66,11 +66,14 @@ void InterfaceSupport::trace(const char* result_type, const char* header) {
|
||||
|
||||
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) {
|
||||
|
@ -127,6 +127,7 @@ Thread::Thread() {
|
||||
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 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
|
||||
// We could enter a safepoint here and thus have a gc
|
||||
InterfaceSupport::check_gc_alot();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -191,6 +191,9 @@ class Thread: public ThreadShadow {
|
||||
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 @@ class Thread: public ThreadShadow {
|
||||
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);
|
||||
|
@ -531,6 +531,7 @@ void VMThread::execute(VM_Operation* op) {
|
||||
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);
|
||||
|
||||
|
@ -41,19 +41,6 @@ BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
|
||||
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();
|
||||
|
@ -93,10 +93,12 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
|
||||
// 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 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// Convenience class wrapping BitMap which provides multiple bits per slot.
|
||||
class BitMap2D VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -36,3 +36,4 @@ d5a1223e961891564de25c39fba6f2442d0fb045 jdk7-b57
|
||||
2a5a1b269e89f27ebe419ef4cf6e66a3face0df1 jdk7-b59
|
||||
0c3ef2d612a47667829eb17a192decef23f1c536 jdk7-b60
|
||||
f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61
|
||||
12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62
|
||||
|
@ -506,6 +506,19 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
|
||||
|
||||
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 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
|
||||
return;
|
||||
}
|
||||
|
||||
isTopDown = bmpParam.isTopDown();
|
||||
|
||||
int maxBandOffset = bandOffsets[0];
|
||||
for (int i = 1; i < bandOffsets.length; i++)
|
||||
if (bandOffsets[i] > maxBandOffset)
|
||||
@ -1299,7 +1310,7 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
|
||||
stream.writeInt(w);
|
||||
|
||||
// height
|
||||
stream.writeInt(h);
|
||||
stream.writeInt(isTopDown ? -h : h);
|
||||
|
||||
// number of planes
|
||||
stream.writeShort(1);
|
||||
|
@ -27,6 +27,8 @@ package com.sun.imageio.plugins.common;
|
||||
|
||||
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 @@ public class ReaderUtil {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -215,17 +215,21 @@ public class JPEG {
|
||||
public static class JCS {
|
||||
public static final ColorSpace sRGB =
|
||||
ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
public static final ColorSpace YCC;
|
||||
|
||||
static {
|
||||
ColorSpace cs = null;
|
||||
try {
|
||||
cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// PYCC.pf may not always be installed
|
||||
} finally {
|
||||
YCC = cs;
|
||||
private static ColorSpace YCC = null;
|
||||
private static boolean yccInited = false;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ import java.awt.Rectangle;
|
||||
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.io.IOException;
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
/** 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 @@ public class JPEGImageReader extends ImageReader {
|
||||
!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 @@ public class JPEGImageReader extends ImageReader {
|
||||
* 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 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
|
||||
// Returns null if it can't be represented
|
||||
return getImageType(colorSpaceCode);
|
||||
return getImageType(colorSpaceCode).getType();
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
}
|
||||
@ -758,13 +726,13 @@ public class JPEGImageReader extends ImageReader {
|
||||
|
||||
// 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 @@ public class JPEGImageReader extends ImageReader {
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
break;
|
||||
}
|
||||
|
||||
return list.iterator();
|
||||
return new ImageTypeIterator(list.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -872,6 +840,10 @@ public class JPEGImageReader extends ImageReader {
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
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 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -812,7 +812,7 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
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 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
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 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
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 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
if (alpha) {
|
||||
retval = JPEG.JCS_YCCA;
|
||||
} else {
|
||||
|
@ -490,7 +490,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable {
|
||||
}
|
||||
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';
|
||||
|
@ -45,6 +45,7 @@ import java.util.ArrayList;
|
||||
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 @@ public class WBMPImageReader extends ImageReader {
|
||||
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 @@ public class WBMPImageReader extends ImageReader {
|
||||
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.
|
||||
|
@ -33,9 +33,13 @@ import javax.imageio.spi.ServiceRegistry;
|
||||
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 @@ public class WBMPImageReaderSpi extends ImageReaderSpi {
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -445,18 +445,19 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
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;
|
||||
|
@ -79,8 +79,9 @@ public abstract class GraphicsEnvironment {
|
||||
|
||||
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()) {
|
||||
|
@ -863,11 +863,16 @@ public class ICC_Profile implements Serializable {
|
||||
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 @@ public class ICC_Profile implements Serializable {
|
||||
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 @@ public class ICC_Profile implements Serializable {
|
||||
}
|
||||
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
fis = new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
return f;
|
||||
}
|
||||
return fis;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@ package javax.imageio;
|
||||
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 @@ public final class ImageIO {
|
||||
} 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);
|
||||
|
@ -160,6 +160,13 @@ public class TrueTypeFont extends FileFont {
|
||||
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 @@ public class TrueTypeFont extends FileFont {
|
||||
* 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 @@ public class TrueTypeFont extends FileFont {
|
||||
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 @@ public class TrueTypeFont extends FileFont {
|
||||
|
||||
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 class TrueTypeFont extends FileFont {
|
||||
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 class TrueTypeFont extends FileFont {
|
||||
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;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ public final class PiscesCache {
|
||||
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;
|
||||
|
@ -1783,7 +1783,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
|
||||
struct jpeg_source_mgr *src;
|
||||
JSAMPROW scanLinePtr;
|
||||
JSAMPROW scanLinePtr = NULL;
|
||||
jint bands[MAX_BANDS];
|
||||
int i, j;
|
||||
jint *body;
|
||||
@ -1819,7 +1819,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
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 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
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 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
buffer);
|
||||
JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
|
||||
}
|
||||
free(scanLinePtr);
|
||||
if (scanLinePtr != NULL) {
|
||||
free(scanLinePtr);
|
||||
scanLinePtr = NULL;
|
||||
}
|
||||
return data->abortFlag;
|
||||
}
|
||||
|
||||
@ -1938,6 +1931,23 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
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 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
scanlineLimit = sourceYStart+sourceHeight;
|
||||
pixelLimit = scanLinePtr
|
||||
+(sourceXStart+sourceWidth)*cinfo->num_components;
|
||||
+(sourceXStart+sourceWidth)*cinfo->output_components;
|
||||
|
||||
pixelStride = stepX*cinfo->num_components;
|
||||
pixelStride = stepX*cinfo->output_components;
|
||||
targetLine = 0;
|
||||
|
||||
while ((data->abortFlag == JNI_FALSE)
|
||||
@ -1982,12 +1992,12 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
// 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++) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
5
jdk/test/javax/imageio/CachePremissionsTest/rw.policy
Normal file
5
jdk/test/javax/imageio/CachePremissionsTest/rw.policy
Normal file
@ -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";
|
||||
};
|
5
jdk/test/javax/imageio/CachePremissionsTest/rwd.policy
Normal file
5
jdk/test/javax/imageio/CachePremissionsTest/rwd.policy
Normal file
@ -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";
|
||||
};
|
5
jdk/test/javax/imageio/CachePremissionsTest/w.policy
Normal file
5
jdk/test/javax/imageio/CachePremissionsTest/w.policy
Normal file
@ -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";
|
||||
};
|
142
jdk/test/javax/imageio/plugins/bmp/TopDownTest.java
Normal file
142
jdk/test/javax/imageio/plugins/bmp/TopDownTest.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
179
jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
Normal file
179
jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
131
jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java
Normal file
131
jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
58
jdk/test/sun/pisces/ScaleTest.java
Normal file
58
jdk/test/sun/pisces/ScaleTest.java
Normal file
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user