RFR(M): 7163191: G1: introduce a "heap spanning table" abstraction

John Cuthbertson john.cuthbertson at oracle.com
Tue Feb 19 21:56:38 UTC 2013

Hi Bengt,

Thanks for taking a look. I've applied your supplied patch and don't 
have an issue with the changes contained therein but there is/was a 
slight bug in HeapRegionSeq::at(). More detailed responses inline....

On 2/15/2013 5:10 AM, Bengt Rutisson wrote:
> Hi John,
> Thanks for putting this together! I definitely think it is a good idea 
> to break some of the logic out of HeapRegionSeq!
> I have a couple of minor things that I would like to clean up. I 
> figured the easiest way was to send you a patch. Please try out the 
> attached patch and see what you think. It should be applied on top of 
> the patch from your webrev.
> I also have a couple of design questions:
> The G1HeapSpanningTableBase::DefaultValue has this comment:
>   // Currently, in all the uses of this class the default value of
>   // array's elements is 0. If this changes in the future we can
>   // allow the subclasses to parametarize it.
> I don't think this will work unless we make the DefaultValue of type T 
> and thus move it into G1HeapSpanningTable. The DefalutValue now is 0 
> which works fine. But when we memset we will write DefalutValue which 
> I guess is int in the enum case (and char in my patch). But when we 
> read we do:
> array[index]
> where array is T* array, so on 64 bit we probably read 64 bits but we 
> only write 32 or less with DefaultValue. So, setting it to anything 
> else than 0 probably won't work.

OK. I kind of agree that this is awkward. What do you think of Thomas' 
idea of having a virtual function default_value() that the subclasses 
have to implement?

> How do you feel about changing the relationship between HeapRegionSeq 
> and G1HeapSpanningTable a bit? Right now HeapRegionSeq inherits from 
> G1HeapSpanningTable but I kind of think that makes the distinction 
> between HeapRegionSeq and G1HeapSpanningTable hard to find. I think it 
> would be clearer if HeapRegionSeq just had an instance of 
> G1HeapSpanningTable and delegated to it.
> That way HeapRegionSeq can be more focused on its responsibilities and 
> G1HeapSpanningTable can be more self contained.

Personally I don't have a strong opinion about this. I typically like 
embedded objects and use them in the hot card cache changes. I guess it 
comes down to what is a good way to model the relationship: "is_a" or 
"contains". If we consider the fast cset arrays case then we either have:

class FastCSetTestArray: public HeapRegionSpanningTable<int> {


class FastCSetTestArray: public CHeapObj<mtGC> {
   HeapRegionSpanningTable<int> _the_table;

It seems a bit more natural to me that the HeapRegionSeq is a heap 
spanning table; the FastCSetTestArray is a heap spanning table. Either 
would work. If we do this then Thomas' idea of the default_value() 
virtual method becomes irrelevant. Its in the eye of the beholder.

> Another thing, which is not only related to this change, is the use of 
> initilize methods. It's a bit strange to me that we use empty 
> constructors and then have to remember to call the initilize methods 
> in the right order. I think it would be good to break the 
> initialize-chain somewhere and go over to using constructors instead. 
> If HeapRegionSeq would not inherit from G1HeapSpanningTable we could 
> set the G1HeapSpanningTable instance in HeapRegionSeq up in its 
> intialize method. That would allow us to use the constructor instead 
> of another level of initialize methods for G1HeapSpanningTable.

I'm not necessarily a fan but it does allow for deferred initialization 
based upon the committed part of the heap so I can see that it 
makes/made sense. Let me make sure I have what you're saying correct. 
Are you saying we should have:

class HeapRegionSeq {
   HeapRegionSpanningTable<HeapRegion*>* _the_table;

HeapRegionSeq::HeapRegionSeq(..): _the_table(NULL), ...

HeapRegionSeq::initialize(...) {
   _the_table = new HeapRegionSpanningTable<HeapRegion*>(...);

Again - no strong opinions other than Thomas' idea makes use of the 
inheritance relationship.

> Finally, there is a comment about why we have the division between 
> G1HeapSpanningTableBase and G1HeapSpanningTable:
> // ... The reason for the
> // split is that we found that compilers like all the methods of a
> // parametarized class to be in the .hpp file and this was the only
> // way to put some of the methods in the .cpp file.
> This is a downside of templates but the .cpp file now only contains 4 
> relevant methods and they are not very large. Does this still motivate 
> the extra complexity introduced by the split into two classes? 
> Currently we also only have one instantation of G1HeapSpanningTable. 
> Will there be more of other types than HeapRegion* or could we just 
> drop the templates?

I kind of agree the split is a bit superfluous. I'll undo the split. If 
we see that there's a performance penalty it can always be reinstated.

Current other uses of the HeapRegionSpanningTable will be for the fast 
cset test arrays (I think the template type parameter is a byte or a 
short) which are currently used for quickly deciding whether a region is 
in the collection set. I know Tony envisioned them for other 
region-based queries. Using the heap spanning table abstraction to 
implement the fast cset test arrays would enable extending them to 
determine whether a region is in the collection set and old in a fairly 
natural way.



> Thanks,
> Bengt
> On 2/14/13 11:16 PM, John Cuthbertson wrote:
>> Hi Everyone,
>> Here's another change from Tony that I've been maintaining since he 
>> left Oracle. Can I have a volunteer look over the changes? They look 
>> good to me. The webrev can be found at: 
>> http://cr.openjdk.java.net/~johnc/7163191/webrev.0/
>> Summary:
>> Currently in G1 there are several tables where a each element is used 
>> to hold some information about a fixed size subdivision of the heap. 
>> For example the HeapRegion table and the fast CSet test tables. This 
>> change encapsulates the base properties of these tables in a generic 
>> heap spanning table and uses the abstraction for the heap region 
>> sequence table. A future change will extend this to the fast cset 
>> test arrays.
>> Testing consisted of the GC test suite with a low marking threshold 
>> and heap verification. Testing did catch an assertion failure that I 
>> have included a small fix for. As with the additional marking 
>> validation changes, if no-one objects, I will push this change with 
>> Tony as the author and myself as a reviewer.
>> JohnC

More information about the hotspot-gc-dev mailing list