1.1 --- a/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp Tue Jan 14 16:40:33 2014 +0100 1.2 +++ b/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp Mon Feb 10 12:51:51 2014 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -25,10 +25,10 @@ 1.11 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP 1.12 #define SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP 1.13 1.14 -#include "memory/genOopClosures.hpp" 1.15 -#include "memory/generation.hpp" 1.16 +#include "memory/iterator.hpp" 1.17 +#include "oops/oopsHierarchy.hpp" 1.18 #include "runtime/os.hpp" 1.19 -#include "utilities/taskqueue.hpp" 1.20 +#include "utilities/debug.hpp" 1.21 1.22 // A BufferingOops closure tries to separate out the cost of finding roots 1.23 // from the cost of applying closures to them. It maintains an array of 1.24 @@ -41,60 +41,103 @@ 1.25 // The caller must be sure to call "done" to process any unprocessed 1.26 // buffered entriess. 1.27 1.28 -class Generation; 1.29 -class HeapRegion; 1.30 +class BufferingOopClosure: public OopClosure { 1.31 + friend class TestBufferingOopClosure; 1.32 +protected: 1.33 + static const size_t BufferLength = 1024; 1.34 1.35 -class BufferingOopClosure: public OopClosure { 1.36 -protected: 1.37 - enum PrivateConstants { 1.38 - BufferLength = 1024 1.39 - }; 1.40 - 1.41 - StarTask _buffer[BufferLength]; 1.42 - StarTask* _buffer_top; 1.43 - StarTask* _buffer_curr; 1.44 + // We need to know if the buffered addresses contain oops or narrowOops. 1.45 + // We can't tag the addresses the way StarTask does, because we need to 1.46 + // be able to handle unaligned addresses coming from oops embedded in code. 1.47 + // 1.48 + // The addresses for the full-sized oops are filled in from the bottom, 1.49 + // while the addresses for the narrowOops are filled in from the top. 1.50 + OopOrNarrowOopStar _buffer[BufferLength]; 1.51 + OopOrNarrowOopStar* _oop_top; 1.52 + OopOrNarrowOopStar* _narrowOop_bottom; 1.53 1.54 OopClosure* _oc; 1.55 double _closure_app_seconds; 1.56 1.57 - void process_buffer () { 1.58 + 1.59 + bool is_buffer_empty() { 1.60 + return _oop_top == _buffer && _narrowOop_bottom == (_buffer + BufferLength - 1); 1.61 + } 1.62 + 1.63 + bool is_buffer_full() { 1.64 + return _narrowOop_bottom < _oop_top; 1.65 + } 1.66 + 1.67 + // Process addresses containing full-sized oops. 1.68 + void process_oops() { 1.69 + for (OopOrNarrowOopStar* curr = _buffer; curr < _oop_top; ++curr) { 1.70 + _oc->do_oop((oop*)(*curr)); 1.71 + } 1.72 + _oop_top = _buffer; 1.73 + } 1.74 + 1.75 + // Process addresses containing narrow oops. 1.76 + void process_narrowOops() { 1.77 + for (OopOrNarrowOopStar* curr = _buffer + BufferLength - 1; curr > _narrowOop_bottom; --curr) { 1.78 + _oc->do_oop((narrowOop*)(*curr)); 1.79 + } 1.80 + _narrowOop_bottom = _buffer + BufferLength - 1; 1.81 + } 1.82 + 1.83 + // Apply the closure to all oops and clear the buffer. 1.84 + // Accumulate the time it took. 1.85 + void process_buffer() { 1.86 double start = os::elapsedTime(); 1.87 - for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) { 1.88 - if (curr->is_narrow()) { 1.89 - assert(UseCompressedOops, "Error"); 1.90 - _oc->do_oop((narrowOop*)(*curr)); 1.91 - } else { 1.92 - _oc->do_oop((oop*)(*curr)); 1.93 - } 1.94 - } 1.95 - _buffer_curr = _buffer; 1.96 + 1.97 + process_oops(); 1.98 + process_narrowOops(); 1.99 + 1.100 _closure_app_seconds += (os::elapsedTime() - start); 1.101 } 1.102 1.103 - template <class T> inline void do_oop_work(T* p) { 1.104 - if (_buffer_curr == _buffer_top) { 1.105 + void process_buffer_if_full() { 1.106 + if (is_buffer_full()) { 1.107 process_buffer(); 1.108 } 1.109 - StarTask new_ref(p); 1.110 - *_buffer_curr = new_ref; 1.111 - ++_buffer_curr; 1.112 + } 1.113 + 1.114 + void add_narrowOop(narrowOop* p) { 1.115 + assert(!is_buffer_full(), "Buffer should not be full"); 1.116 + *_narrowOop_bottom = (OopOrNarrowOopStar)p; 1.117 + _narrowOop_bottom--; 1.118 + } 1.119 + 1.120 + void add_oop(oop* p) { 1.121 + assert(!is_buffer_full(), "Buffer should not be full"); 1.122 + *_oop_top = (OopOrNarrowOopStar)p; 1.123 + _oop_top++; 1.124 } 1.125 1.126 public: 1.127 - virtual void do_oop(narrowOop* p) { do_oop_work(p); } 1.128 - virtual void do_oop(oop* p) { do_oop_work(p); } 1.129 + virtual void do_oop(narrowOop* p) { 1.130 + process_buffer_if_full(); 1.131 + add_narrowOop(p); 1.132 + } 1.133 1.134 - void done () { 1.135 - if (_buffer_curr > _buffer) { 1.136 + virtual void do_oop(oop* p) { 1.137 + process_buffer_if_full(); 1.138 + add_oop(p); 1.139 + } 1.140 + 1.141 + void done() { 1.142 + if (!is_buffer_empty()) { 1.143 process_buffer(); 1.144 } 1.145 } 1.146 - double closure_app_seconds () { 1.147 + 1.148 + double closure_app_seconds() { 1.149 return _closure_app_seconds; 1.150 } 1.151 - BufferingOopClosure (OopClosure *oc) : 1.152 + 1.153 + BufferingOopClosure(OopClosure *oc) : 1.154 _oc(oc), 1.155 - _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength), 1.156 + _oop_top(_buffer), 1.157 + _narrowOop_bottom(_buffer + BufferLength - 1), 1.158 _closure_app_seconds(0.0) { } 1.159 }; 1.160