mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
8069016: Add BarrierSet downcast support
Add FakeRttiSupport utility and use to provide barrier_set_cast. Reviewed-by: jmasa, sangheki
This commit is contained in:
parent
1426bc9dc1
commit
40d3986051
32 changed files with 289 additions and 131 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2012, 2014 SAP AG. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
|
@ -2204,7 +2204,8 @@ void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register t
|
|||
|
||||
// Write the card table byte if needed.
|
||||
void MacroAssembler::card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp) {
|
||||
CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set();
|
||||
CardTableModRefBS* bs =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef ||
|
||||
bs->kind() == BarrierSet::CardTableExtension, "wrong barrier");
|
||||
#ifdef ASSERT
|
||||
|
@ -2310,9 +2311,8 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_v
|
|||
Label& filtered = (filtered_ext != NULL) ? *filtered_ext : filtered_int;
|
||||
assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2);
|
||||
|
||||
G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::G1SATBCT ||
|
||||
bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier");
|
||||
G1SATBCardTableLoggingModRefBS* bs =
|
||||
barrier_set_cast<G1SATBCardTableLoggingModRefBS>(Universe::heap()->barrier_set());
|
||||
|
||||
// Does store cross heap regions?
|
||||
if (G1RSBarrierRegionFilter) {
|
||||
|
|
|
@ -694,7 +694,7 @@ class StubGenerator: public StubCodeGenerator {
|
|||
__ release();
|
||||
}
|
||||
|
||||
CardTableModRefBS* const ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* const ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
assert_different_registers(addr, count, tmp);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -916,7 +916,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
|||
Register cardtable = G5;
|
||||
Register tmp = G1_scratch;
|
||||
Register tmp2 = G3_scratch;
|
||||
jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base;
|
||||
jbyte* byte_map_base = barrier_set_cast<CardTableModRefBS>(bs)->byte_map_base;
|
||||
|
||||
Label not_already_dirty, restart, refill, young_card;
|
||||
|
||||
|
|
|
@ -3858,9 +3858,8 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val
|
|||
|
||||
if (new_val == G0) return;
|
||||
|
||||
G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::G1SATBCT ||
|
||||
bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier");
|
||||
G1SATBCardTableLoggingModRefBS* bs =
|
||||
barrier_set_cast<G1SATBCardTableLoggingModRefBS>(Universe::heap()->barrier_set());
|
||||
|
||||
if (G1RSBarrierRegionFilter) {
|
||||
xor3(store_addr, new_val, tmp);
|
||||
|
@ -3904,7 +3903,8 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val
|
|||
void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) {
|
||||
// If we're writing constant NULL, we can skip the write barrier.
|
||||
if (new_val == G0) return;
|
||||
CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set();
|
||||
CardTableModRefBS* bs =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef ||
|
||||
bs->kind() == BarrierSet::CardTableExtension, "wrong barrier");
|
||||
card_table_write(bs->byte_map_base, tmp, store_addr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -1019,7 +1019,7 @@ class StubGenerator: public StubCodeGenerator {
|
|||
case BarrierSet::CardTableModRef:
|
||||
case BarrierSet::CardTableExtension:
|
||||
{
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
assert_different_registers(addr, count, tmp);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -1718,8 +1718,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
|||
// arg0: store_address
|
||||
Address store_addr(rbp, 2*BytesPerWord);
|
||||
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
Label done;
|
||||
|
|
|
@ -4204,8 +4204,8 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr,
|
|||
Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
|
||||
PtrQueue::byte_offset_of_buf()));
|
||||
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
Label done;
|
||||
|
@ -4305,7 +4305,7 @@ void MacroAssembler::store_check_part_1(Register obj) {
|
|||
void MacroAssembler::store_check_part_2(Register obj) {
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
// The calculation for byte_map_base is as follows:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -752,7 +752,7 @@ class StubGenerator: public StubCodeGenerator {
|
|||
case BarrierSet::CardTableModRef:
|
||||
case BarrierSet::CardTableExtension:
|
||||
{
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
Label L_loop;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -1272,7 +1272,7 @@ class StubGenerator: public StubCodeGenerator {
|
|||
case BarrierSet::CardTableModRef:
|
||||
case BarrierSet::CardTableExtension:
|
||||
{
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
Label L_loop;
|
||||
|
|
|
@ -1582,9 +1582,9 @@ void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_Opr
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
|
||||
|
||||
assert(sizeof(*((CardTableModRefBS*)_bs)->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
LIR_Const* card_table_base = new LIR_Const(((CardTableModRefBS*)_bs)->byte_map_base);
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(_bs);
|
||||
assert(sizeof(*(ct->byte_map_base)) == sizeof(jbyte), "adjust this code");
|
||||
LIR_Const* card_table_base = new LIR_Const(ct->byte_map_base);
|
||||
if (addr->is_address()) {
|
||||
LIR_Address* address = addr->as_address_ptr();
|
||||
// ptr cannot be an object because we use this barrier for array card marks
|
||||
|
@ -1609,7 +1609,6 @@ void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc*
|
|||
__ move(new LIR_Address(FrameMap::Rthread_opr, in_bytes(JavaThread::card_table_base_offset()), T_ADDRESS), tmp);
|
||||
}
|
||||
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)_bs;
|
||||
LIR_Address *card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTableModRefBS::card_shift, 0, T_BYTE);
|
||||
if(((int)ct->byte_map_base & 0xff) == 0) {
|
||||
__ move(tmp, card_addr);
|
||||
|
|
|
@ -340,8 +340,8 @@ void decode_env::print_address(address adr) {
|
|||
}
|
||||
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
if (bs->kind() == BarrierSet::CardTableModRef &&
|
||||
adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) {
|
||||
if (bs->is_a(BarrierSet::CardTableModRef) &&
|
||||
adr == (address)(barrier_set_cast<CardTableModRefBS>(bs)->byte_map_base)) {
|
||||
st->print("word_map_base");
|
||||
if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr);
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -1440,7 +1440,7 @@ public:
|
|||
CMCountDataClosureBase(G1CollectedHeap* g1h,
|
||||
BitMap* region_bm, BitMap* card_bm):
|
||||
_g1h(g1h), _cm(g1h->concurrent_mark()),
|
||||
_ct_bs((CardTableModRefBS*) (g1h->barrier_set())),
|
||||
_ct_bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
|
||||
_region_bm(region_bm), _card_bm(card_bm) { }
|
||||
};
|
||||
|
||||
|
@ -3111,7 +3111,7 @@ class AggregateCountDataHRClosure: public HeapRegionClosure {
|
|||
BitMap* cm_card_bm,
|
||||
uint max_worker_id) :
|
||||
_g1h(g1h), _cm(g1h->concurrent_mark()),
|
||||
_ct_bs((CardTableModRefBS*) (g1h->barrier_set())),
|
||||
_ct_bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
|
||||
_cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { }
|
||||
|
||||
bool doHeapRegion(HeapRegion* hr) {
|
||||
|
|
|
@ -1274,7 +1274,7 @@ public:
|
|||
virtual bool is_in_closed_subset(const void* p) const;
|
||||
|
||||
G1SATBCardTableLoggingModRefBS* g1_barrier_set() {
|
||||
return (G1SATBCardTableLoggingModRefBS*) barrier_set();
|
||||
return barrier_set_cast<G1SATBCardTableLoggingModRefBS>(barrier_set());
|
||||
}
|
||||
|
||||
// This resets the card table to all zeros. It is used after
|
||||
|
|
|
@ -33,8 +33,11 @@
|
|||
#include "runtime/orderAccess.inline.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap, BarrierSet::Name kind) :
|
||||
CardTableModRefBS(whole_heap, kind) { }
|
||||
G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(
|
||||
MemRegion whole_heap,
|
||||
const BarrierSet::FakeRtti& fake_rtti) :
|
||||
CardTableModRefBS(whole_heap, fake_rtti.add_tag(BarrierSet::G1SATBCT))
|
||||
{ }
|
||||
|
||||
void G1SATBCardTableModRefBS::enqueue(oop pre_val) {
|
||||
// Nulls should have been already filtered.
|
||||
|
@ -130,7 +133,7 @@ void G1SATBCardTableLoggingModRefBSChangedListener::on_commit(uint start_idx, si
|
|||
|
||||
G1SATBCardTableLoggingModRefBS::
|
||||
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap) :
|
||||
G1SATBCardTableModRefBS(whole_heap, BarrierSet::G1SATBCTLogging),
|
||||
G1SATBCardTableModRefBS(whole_heap, BarrierSet::FakeRtti(G1SATBCTLogging)),
|
||||
_dcqs(JavaThread::dirty_card_queue_set()),
|
||||
_listener()
|
||||
{
|
||||
|
@ -203,7 +206,7 @@ G1SATBCardTableLoggingModRefBS::write_ref_field_static(void* field,
|
|||
if (new_val == NULL) return;
|
||||
// Otherwise, log it.
|
||||
G1SATBCardTableLoggingModRefBS* g1_bs =
|
||||
(G1SATBCardTableLoggingModRefBS*)Universe::heap()->barrier_set();
|
||||
barrier_set_cast<G1SATBCardTableLoggingModRefBS>(Universe::heap()->barrier_set());
|
||||
g1_bs->write_ref_field_work(field, new_val);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ protected:
|
|||
g1_young_gen = CT_MR_BS_last_reserved << 1
|
||||
};
|
||||
|
||||
G1SATBCardTableModRefBS(MemRegion whole_heap, BarrierSet::Name kind);
|
||||
G1SATBCardTableModRefBS(MemRegion whole_heap, const BarrierSet::FakeRtti& fake_rtti);
|
||||
~G1SATBCardTableModRefBS() { }
|
||||
|
||||
public:
|
||||
|
@ -53,10 +53,6 @@ public:
|
|||
// pre-marking object graph.
|
||||
static void enqueue(oop pre_val);
|
||||
|
||||
bool is_a(BarrierSet::Name bsn) {
|
||||
return bsn == BarrierSet::G1SATBCT || CardTableModRefBS::is_a(bsn);
|
||||
}
|
||||
|
||||
virtual bool has_write_ref_pre_barrier() { return true; }
|
||||
|
||||
// This notes that we don't need to access any BarrierSet data
|
||||
|
@ -128,6 +124,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<G1SATBCardTableModRefBS> {
|
||||
static const BarrierSet::Name value = BarrierSet::G1SATBCT;
|
||||
};
|
||||
|
||||
class G1SATBCardTableLoggingModRefBSChangedListener : public G1MappingChangedListener {
|
||||
private:
|
||||
G1SATBCardTableLoggingModRefBS* _card_table;
|
||||
|
@ -159,11 +160,6 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS {
|
|||
|
||||
virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); }
|
||||
|
||||
bool is_a(BarrierSet::Name bsn) {
|
||||
return bsn == BarrierSet::G1SATBCTLogging ||
|
||||
G1SATBCardTableModRefBS::is_a(bsn);
|
||||
}
|
||||
|
||||
void write_ref_field_work(void* field, oop new_val, bool release = false);
|
||||
|
||||
// Can be called from static contexts.
|
||||
|
@ -177,4 +173,9 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS {
|
|||
void write_ref_array_work(MemRegion mr) { invalidate(mr); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<G1SATBCardTableLoggingModRefBS> {
|
||||
static const BarrierSet::Name value = BarrierSet::G1SATBCTLogging;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP
|
||||
|
|
|
@ -193,7 +193,7 @@ void HeapRegion::par_clear() {
|
|||
HeapRegionRemSet* hrrs = rem_set();
|
||||
hrrs->clear();
|
||||
CardTableModRefBS* ct_bs =
|
||||
(CardTableModRefBS*)G1CollectedHeap::heap()->barrier_set();
|
||||
barrier_set_cast<CardTableModRefBS>(G1CollectedHeap::heap()->barrier_set());
|
||||
ct_bs->clear(MemRegion(bottom(), end()));
|
||||
}
|
||||
|
||||
|
@ -643,13 +643,9 @@ public:
|
|||
// _vo == UseNextMarking -> use "next" marking information,
|
||||
// _vo == UseMarkWord -> use mark word from object header.
|
||||
VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) :
|
||||
_g1h(g1h), _bs(NULL), _containing_obj(NULL),
|
||||
_failures(false), _n_failures(0), _vo(vo)
|
||||
{
|
||||
BarrierSet* bs = _g1h->barrier_set();
|
||||
if (bs->is_a(BarrierSet::CardTableModRef))
|
||||
_bs = (CardTableModRefBS*)bs;
|
||||
}
|
||||
_g1h(g1h), _bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
|
||||
_containing_obj(NULL), _failures(false), _n_failures(0), _vo(vo)
|
||||
{ }
|
||||
|
||||
void set_containing_obj(oop obj) {
|
||||
_containing_obj = obj;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -81,7 +81,7 @@ class CheckForUnmarkedObjects : public ObjectClosure {
|
|||
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
|
||||
|
||||
_young_gen = heap->young_gen();
|
||||
_card_table = (CardTableExtension*)heap->barrier_set();
|
||||
_card_table = barrier_set_cast<CardTableExtension>(heap->barrier_set());
|
||||
// No point in asserting barrier set type here. Need to make CardTableExtension
|
||||
// a unique barrier set type.
|
||||
}
|
||||
|
@ -341,7 +341,9 @@ void CardTableExtension::verify_all_young_refs_precise() {
|
|||
|
||||
PSOldGen* old_gen = heap->old_gen();
|
||||
|
||||
CheckForPreciseMarks check(heap->young_gen(), (CardTableExtension*)heap->barrier_set());
|
||||
CheckForPreciseMarks check(
|
||||
heap->young_gen(),
|
||||
barrier_set_cast<CardTableExtension>(heap->barrier_set()));
|
||||
|
||||
old_gen->oop_iterate_no_header(&check);
|
||||
|
||||
|
@ -349,8 +351,8 @@ void CardTableExtension::verify_all_young_refs_precise() {
|
|||
}
|
||||
|
||||
void CardTableExtension::verify_all_young_refs_precise_helper(MemRegion mr) {
|
||||
CardTableExtension* card_table = (CardTableExtension*)Universe::heap()->barrier_set();
|
||||
// FIX ME ASSERT HERE
|
||||
CardTableExtension* card_table =
|
||||
barrier_set_cast<CardTableExtension>(Universe::heap()->barrier_set());
|
||||
|
||||
jbyte* bot = card_table->byte_for(mr.start());
|
||||
jbyte* top = card_table->byte_for(mr.end());
|
||||
|
|
|
@ -54,10 +54,16 @@ class CardTableExtension : public CardTableModRefBS {
|
|||
};
|
||||
|
||||
CardTableExtension(MemRegion whole_heap) :
|
||||
CardTableModRefBS(whole_heap, BarrierSet::CardTableModRef) { }
|
||||
|
||||
// Too risky for the 4/10/02 putback
|
||||
// BarrierSet::Name kind() { return BarrierSet::CardTableExtension; }
|
||||
CardTableModRefBS(
|
||||
whole_heap,
|
||||
// Concrete tag should be BarrierSet::CardTableExtension.
|
||||
// That will presently break things in a bunch of places though.
|
||||
// The concrete tag is used as a dispatch key in many places, and
|
||||
// CardTableExtension does not correctly dispatch in some of those
|
||||
// uses. This will be addressed as part of a reorganization of the
|
||||
// BarrierSet hierarchy.
|
||||
BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableExtension))
|
||||
{ }
|
||||
|
||||
// Scavenge support
|
||||
void scavenge_contents_parallel(ObjectStartArray* start_array,
|
||||
|
@ -110,4 +116,9 @@ class CardTableExtension : public CardTableModRefBS {
|
|||
#endif // ASSERT
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<CardTableExtension> {
|
||||
static const BarrierSet::Name value = BarrierSet::CardTableExtension;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_CARDTABLEEXTENSION_HPP
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -233,16 +232,13 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
|||
young_gen->to_space()->is_empty();
|
||||
young_gen_empty = eden_empty && survivors_empty;
|
||||
|
||||
BarrierSet* bs = heap->barrier_set();
|
||||
if (bs->is_a(BarrierSet::ModRef)) {
|
||||
ModRefBarrierSet* modBS = (ModRefBarrierSet*)bs;
|
||||
ModRefBarrierSet* modBS = barrier_set_cast<ModRefBarrierSet>(heap->barrier_set());
|
||||
MemRegion old_mr = heap->old_gen()->reserved();
|
||||
if (young_gen_empty) {
|
||||
modBS->clear(MemRegion(old_mr.start(), old_mr.end()));
|
||||
} else {
|
||||
modBS->invalidate(MemRegion(old_mr.start(), old_mr.end()));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete metaspaces for unloaded class loaders and clean up loader_data graph
|
||||
ClassLoaderDataGraph::purge();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -111,8 +111,8 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) {
|
|||
|
||||
Universe::heap()->barrier_set()->resize_covered_region(cmr);
|
||||
|
||||
CardTableModRefBS* _ct = (CardTableModRefBS*)Universe::heap()->barrier_set();
|
||||
assert (_ct->kind() == BarrierSet::CardTableModRef, "Sanity");
|
||||
CardTableModRefBS* _ct =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
|
||||
// Verify that the start and end of this generation is the start of a card.
|
||||
// If this wasn't true, a single card could span more than one generation,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -1050,17 +1050,13 @@ void PSParallelCompact::post_compact()
|
|||
bool young_gen_empty = eden_empty && from_space->is_empty() &&
|
||||
to_space->is_empty();
|
||||
|
||||
BarrierSet* bs = heap->barrier_set();
|
||||
if (bs->is_a(BarrierSet::ModRef)) {
|
||||
ModRefBarrierSet* modBS = (ModRefBarrierSet*)bs;
|
||||
ModRefBarrierSet* modBS = barrier_set_cast<ModRefBarrierSet>(heap->barrier_set());
|
||||
MemRegion old_mr = heap->old_gen()->reserved();
|
||||
|
||||
if (young_gen_empty) {
|
||||
modBS->clear(MemRegion(old_mr.start(), old_mr.end()));
|
||||
} else {
|
||||
modBS->invalidate(MemRegion(old_mr.start(), old_mr.end()));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete metaspaces for unloaded class loaders and clean up loader_data graph
|
||||
ClassLoaderDataGraph::purge();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -866,9 +865,7 @@ void PSScavenge::initialize() {
|
|||
NULL); // header provides liveness info
|
||||
|
||||
// Cache the cardtable
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
_card_table = (CardTableExtension*)bs;
|
||||
_card_table = barrier_set_cast<CardTableExtension>(heap->barrier_set());
|
||||
|
||||
_counters = new CollectorCounters("PSScavenge", 0);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. 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
|
||||
|
@ -183,8 +183,8 @@ void OldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) {
|
|||
PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
|
||||
|
||||
assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
|
||||
CardTableExtension* card_table = (CardTableExtension *)Universe::heap()->barrier_set();
|
||||
// FIX ME! Assert that card_table is the type we believe it to be.
|
||||
CardTableExtension* card_table =
|
||||
barrier_set_cast<CardTableExtension>(Universe::heap()->barrier_set());
|
||||
|
||||
card_table->scavenge_contents_parallel(_gen->start_array(),
|
||||
_gen->object_space(),
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "memory/memRegion.hpp"
|
||||
#include "oops/oopsHierarchy.hpp"
|
||||
#include "utilities/fakeRttiSupport.hpp"
|
||||
|
||||
// This class provides the interface between a barrier implementation and
|
||||
// the rest of the system.
|
||||
|
@ -34,18 +35,61 @@
|
|||
class BarrierSet: public CHeapObj<mtGC> {
|
||||
friend class VMStructs;
|
||||
public:
|
||||
enum Name {
|
||||
ModRef,
|
||||
CardTableModRef,
|
||||
CardTableExtension,
|
||||
G1SATBCT,
|
||||
G1SATBCTLogging
|
||||
// Fake RTTI support. For a derived class T to participate
|
||||
// - T must have a corresponding Name entry.
|
||||
// - GetName<T> must be specialized to return the corresponding Name
|
||||
// entry.
|
||||
// - If T is a base class, the constructor must have a FakeRtti
|
||||
// parameter and pass it up to its base class, with the tag set
|
||||
// augmented with the corresponding Name entry.
|
||||
// - If T is a concrete class, the constructor must create a
|
||||
// FakeRtti object whose tag set includes the corresponding Name
|
||||
// entry, and pass it up to its base class.
|
||||
|
||||
enum Name { // associated class
|
||||
ModRef, // ModRefBarrierSet
|
||||
CardTableModRef, // CardTableModRefBS
|
||||
CardTableForRS, // CardTableModRefBSForCTRS
|
||||
CardTableExtension, // CardTableExtension
|
||||
G1SATBCT, // G1SATBCardTableModRefBS
|
||||
G1SATBCTLogging // G1SATBCardTableLoggingModRefBS
|
||||
};
|
||||
|
||||
protected:
|
||||
typedef FakeRttiSupport<BarrierSet, Name> FakeRtti;
|
||||
|
||||
private:
|
||||
FakeRtti _fake_rtti;
|
||||
|
||||
// Metafunction mapping a class derived from BarrierSet to the
|
||||
// corresponding Name enum tag.
|
||||
template<typename T> struct GetName;
|
||||
|
||||
// Downcast argument to a derived barrier set type.
|
||||
// The cast is checked in a debug build.
|
||||
// T must have a specialization for BarrierSet::GetName<T>.
|
||||
template<typename T>
|
||||
friend T* barrier_set_cast(BarrierSet* bs) {
|
||||
assert(bs->is_a(BarrierSet::GetName<T>::value), "wrong type of barrier set");
|
||||
return static_cast<T*>(bs);
|
||||
}
|
||||
|
||||
public:
|
||||
// Note: This is not presently the Name corresponding to the
|
||||
// concrete class of this object.
|
||||
BarrierSet::Name kind() const { return _fake_rtti.concrete_tag(); }
|
||||
|
||||
// Test whether this object is of the type corresponding to bsn.
|
||||
bool is_a(BarrierSet::Name bsn) const { return _fake_rtti.has_tag(bsn); }
|
||||
|
||||
// End of fake RTTI support.
|
||||
|
||||
public:
|
||||
enum Flags {
|
||||
None = 0,
|
||||
TargetUninitialized = 1
|
||||
};
|
||||
|
||||
protected:
|
||||
// Some barrier sets create tables whose elements correspond to parts of
|
||||
// the heap; the CardTableModRefBS is an example. Such barrier sets will
|
||||
|
@ -53,17 +97,12 @@ protected:
|
|||
// "covering" parts of the heap that are committed. At most one covered
|
||||
// region per generation is needed.
|
||||
static const int _max_covered_regions = 2;
|
||||
Name _kind;
|
||||
|
||||
BarrierSet(Name kind) : _kind(kind) { }
|
||||
BarrierSet(const FakeRtti& fake_rtti) : _fake_rtti(fake_rtti) { }
|
||||
~BarrierSet() { }
|
||||
|
||||
public:
|
||||
|
||||
// To get around prohibition on RTTI.
|
||||
BarrierSet::Name kind() { return _kind; }
|
||||
virtual bool is_a(BarrierSet::Name bsn) = 0;
|
||||
|
||||
// These operations indicate what kind of barriers the BarrierSet has.
|
||||
virtual bool has_read_ref_barrier() = 0;
|
||||
virtual bool has_read_prim_barrier() = 0;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
template <class T> void BarrierSet::write_ref_field_pre(T* field, oop new_val) {
|
||||
if (kind() == CardTableModRef) {
|
||||
((CardTableModRefBS*)this)->inline_write_ref_field_pre(field, new_val);
|
||||
barrier_set_cast<CardTableModRefBS>(this)->inline_write_ref_field_pre(field, new_val);
|
||||
} else {
|
||||
write_ref_field_pre_work(field, new_val);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ template <class T> void BarrierSet::write_ref_field_pre(T* field, oop new_val) {
|
|||
|
||||
void BarrierSet::write_ref_field(void* field, oop new_val, bool release) {
|
||||
if (kind() == CardTableModRef) {
|
||||
((CardTableModRefBS*)this)->inline_write_ref_field(field, new_val, release);
|
||||
barrier_set_cast<CardTableModRefBS>(this)->inline_write_ref_field(field, new_val, release);
|
||||
} else {
|
||||
write_ref_field_work(field, new_val, release);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void BarrierSet::write_ref_array(HeapWord* start, size_t count) {
|
|||
|
||||
inline void BarrierSet::write_region(MemRegion mr) {
|
||||
if (kind() == CardTableModRef) {
|
||||
((CardTableModRefBS*)this)->inline_write_region(mr);
|
||||
barrier_set_cast<CardTableModRefBS>(this)->inline_write_region(mr);
|
||||
} else {
|
||||
write_region_work(mr);
|
||||
}
|
||||
|
|
|
@ -53,8 +53,10 @@ size_t CardTableModRefBS::compute_byte_map_size()
|
|||
return align_size_up(_guard_index + 1, MAX2(_page_size, granularity));
|
||||
}
|
||||
|
||||
CardTableModRefBS::CardTableModRefBS(MemRegion whole_heap, BarrierSet::Name kind) :
|
||||
ModRefBarrierSet(kind),
|
||||
CardTableModRefBS::CardTableModRefBS(
|
||||
MemRegion whole_heap,
|
||||
const BarrierSet::FakeRtti& fake_rtti) :
|
||||
ModRefBarrierSet(fake_rtti.add_tag(BarrierSet::CardTableModRef)),
|
||||
_whole_heap(whole_heap),
|
||||
_guard_index(0),
|
||||
_guard_region(),
|
||||
|
|
|
@ -279,11 +279,6 @@ public:
|
|||
static int precleaned_card_val() { return precleaned_card; }
|
||||
static int deferred_card_val() { return deferred_card; }
|
||||
|
||||
// For RTTI simulation.
|
||||
bool is_a(BarrierSet::Name bsn) {
|
||||
return bsn == BarrierSet::CardTableModRef || ModRefBarrierSet::is_a(bsn);
|
||||
}
|
||||
|
||||
virtual void initialize();
|
||||
|
||||
// *** Barrier set functions.
|
||||
|
@ -292,7 +287,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
CardTableModRefBS(MemRegion whole_heap, BarrierSet::Name kind);
|
||||
CardTableModRefBS(MemRegion whole_heap, const BarrierSet::FakeRtti& fake_rtti);
|
||||
~CardTableModRefBS();
|
||||
|
||||
// Record a reference update. Note that these versions are precise!
|
||||
|
@ -462,6 +457,11 @@ public:
|
|||
void verify_dirty_region(MemRegion mr) PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<CardTableModRefBS> {
|
||||
static const BarrierSet::Name value = BarrierSet::CardTableModRef;
|
||||
};
|
||||
|
||||
class CardTableRS;
|
||||
|
||||
// A specialization for the CardTableRS gen rem set.
|
||||
|
@ -472,10 +472,24 @@ protected:
|
|||
bool card_may_have_been_dirty(jbyte cv);
|
||||
public:
|
||||
CardTableModRefBSForCTRS(MemRegion whole_heap) :
|
||||
CardTableModRefBS(whole_heap, BarrierSet::CardTableModRef) {}
|
||||
CardTableModRefBS(
|
||||
whole_heap,
|
||||
// Concrete tag should be BarrierSet::CardTableForRS.
|
||||
// That will presently break things in a bunch of places though.
|
||||
// The concrete tag is used as a dispatch key in many places, and
|
||||
// CardTableForRS does not correctly dispatch in some of those
|
||||
// uses. This will be addressed as part of a reorganization of the
|
||||
// BarrierSet hierarchy.
|
||||
BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS))
|
||||
{}
|
||||
|
||||
void set_CTRS(CardTableRS* rs) { _rs = rs; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
|
||||
static const BarrierSet::Name value = BarrierSet::CardTableForRS;
|
||||
};
|
||||
|
||||
|
||||
#endif // SHARE_VM_MEMORY_CARDTABLEMODREFBS_HPP
|
||||
|
|
|
@ -37,10 +37,6 @@ class Generation;
|
|||
class ModRefBarrierSet: public BarrierSet {
|
||||
public:
|
||||
|
||||
bool is_a(BarrierSet::Name bsn) {
|
||||
return bsn == BarrierSet::ModRef;
|
||||
}
|
||||
|
||||
// Barriers only on ref writes.
|
||||
bool has_read_ref_barrier() { return false; }
|
||||
bool has_read_prim_barrier() { return false; }
|
||||
|
@ -60,7 +56,8 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
ModRefBarrierSet(BarrierSet::Name kind) : BarrierSet(kind) { }
|
||||
ModRefBarrierSet(const BarrierSet::FakeRtti& fake_rtti)
|
||||
: BarrierSet(fake_rtti.add_tag(BarrierSet::ModRef)) { }
|
||||
~ModRefBarrierSet() { }
|
||||
|
||||
virtual void write_ref_field_work(void* field, oop new_val, bool release = false) = 0;
|
||||
|
@ -100,4 +97,9 @@ public:
|
|||
virtual void clear(MemRegion mr) = 0;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BarrierSet::GetName<ModRefBarrierSet> {
|
||||
static const BarrierSet::Name value = BarrierSet::ModRef;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_MEMORY_MODREFBARRIERSET_HPP
|
||||
|
|
|
@ -3759,7 +3759,8 @@ void GraphKit::final_sync(IdealKit& ideal) {
|
|||
|
||||
Node* GraphKit::byte_map_base_node() {
|
||||
// Get base of card map
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)(Universe::heap()->barrier_set());
|
||||
CardTableModRefBS* ct =
|
||||
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust users of this code");
|
||||
if (ct->byte_map_base != NULL) {
|
||||
return makecon(TypeRawPtr::make((address)ct->byte_map_base));
|
||||
|
|
|
@ -481,7 +481,6 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
|||
\
|
||||
unchecked_nonstatic_field(ageTable, sizes, sizeof(ageTable::sizes)) \
|
||||
\
|
||||
nonstatic_field(BarrierSet, _kind, BarrierSet::Name) \
|
||||
nonstatic_field(BlockOffsetTable, _bottom, HeapWord*) \
|
||||
nonstatic_field(BlockOffsetTable, _end, HeapWord*) \
|
||||
\
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
|
@ -446,7 +446,7 @@ void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {
|
|||
CreateIntToPtr(
|
||||
CreateAdd(
|
||||
LLVMValue::intptr_constant(
|
||||
(intptr_t) ((CardTableModRefBS *) bs)->byte_map_base),
|
||||
(intptr_t) (barrier_set_cast<CardTableModRefBS>(bs)->byte_map_base)),
|
||||
CreateLShr(
|
||||
CreatePtrToInt(field, SharkType::intptr_type()),
|
||||
LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),
|
||||
|
|
100
hotspot/src/share/vm/utilities/fakeRttiSupport.hpp
Normal file
100
hotspot/src/share/vm/utilities/fakeRttiSupport.hpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_UTILITIES_FAKERTTISUPPORT_HPP
|
||||
#define SHARE_VM_UTILITIES_FAKERTTISUPPORT_HPP
|
||||
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
// Provides support for checked downcasts in a hierarchy of classes.
|
||||
// The base class provides a member of this type, specialized on that
|
||||
// base class and an associated tag type. Tags are small non-negative
|
||||
// integer values uniquely associated with distinct classes in the
|
||||
// hierarchy. A tag type is often an enum type.
|
||||
//
|
||||
// The concrete class specifies the concrete tag.
|
||||
//
|
||||
// The tag set specifies the set of classes in the derivation
|
||||
// sequence. Classes in the derivation sequence add their associated
|
||||
// tag during construction. Given the tag associated with a class, an
|
||||
// object is an instance of that class if the tag is included in the
|
||||
// object's set of recorded tags.
|
||||
//
|
||||
// A tag T is present in a tag set if the T'th bit of the tag set is
|
||||
// one.
|
||||
//
|
||||
// Note: The representation of a tag set being uintx sets an upper
|
||||
// bound on the size of a class hierarchy this utility can be used
|
||||
// with.
|
||||
template<typename T, typename TagType>
|
||||
class FakeRttiSupport VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
// Construct with the indicated concrete tag, and include the
|
||||
// concrete tag in the associated tag set.
|
||||
explicit FakeRttiSupport(TagType concrete_tag) :
|
||||
_tag_set(tag_bit(concrete_tag)), _concrete_tag(concrete_tag) { }
|
||||
|
||||
// Construct with the indicated concrete tag and tag set.
|
||||
// Note: This constructor is public only to allow clients to set up
|
||||
// "unusual" (or perhaps buggy) fake RTTI configurations.
|
||||
FakeRttiSupport(TagType concrete_tag, uintx tag_set) :
|
||||
_tag_set(tag_set), _concrete_tag(validate_tag(concrete_tag)) { }
|
||||
|
||||
// Get the concrete tag.
|
||||
TagType concrete_tag() const { return _concrete_tag; }
|
||||
|
||||
// Test whether tag is in the tag set.
|
||||
bool has_tag(TagType tag) const {
|
||||
return (_tag_set & tag_bit(tag)) != 0;
|
||||
}
|
||||
|
||||
// Return a new support object which is the same as this, except tag
|
||||
// has been added to the tag set. The tag must not already be
|
||||
// present in the tag set.
|
||||
FakeRttiSupport add_tag(TagType tag) const {
|
||||
uintx tbit = tag_bit(tag);
|
||||
assert((_tag_set & tbit) == 0,
|
||||
err_msg("Tag " UINTX_FORMAT " is already present in tag set: " UINTX_FORMAT,
|
||||
(uintx)tag, _tag_set));
|
||||
return FakeRttiSupport(_concrete_tag, _tag_set | tbit);
|
||||
}
|
||||
|
||||
private:
|
||||
uintx _tag_set;
|
||||
TagType _concrete_tag;
|
||||
|
||||
static uintx tag_bit(TagType tag) {
|
||||
return ((uintx)1) << validate_tag(tag);
|
||||
}
|
||||
|
||||
static TagType validate_tag(uintx tag) {
|
||||
// Type of tag is not TagType to dodge useless MacOSX compiler warning.
|
||||
assert(tag < (sizeof(uintx) * BitsPerByte),
|
||||
err_msg("Tag " UINTX_FORMAT " is too large", tag));
|
||||
return static_cast<TagType>(tag);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // include guard
|
Loading…
Add table
Add a link
Reference in a new issue