src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp

Print this page
rev 5821 : imported patch changeBufferingOopClosures

*** 1,7 **** /* ! * Copyright (c) 2001, 2010, 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. --- 1,7 ---- /* ! * Copyright (c) 2001, 2014, 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.
*** 23,101 **** */ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP ! #include "memory/genOopClosures.hpp" ! #include "memory/generation.hpp" #include "runtime/os.hpp" ! #include "utilities/taskqueue.hpp" // A BufferingOops closure tries to separate out the cost of finding roots // from the cost of applying closures to them. It maintains an array of // ref-containing locations. Until the array is full, applying the closure // to an oop* merely records that location in the array. Since this // closure app cost is small, an elapsed timer can approximately attribute // all of this cost to the cost of finding the roots. When the array fills // up, the wrapped closure is applied to all elements, keeping track of // this elapsed time of this process, and leaving the array empty. // The caller must be sure to call "done" to process any unprocessed ! // buffered entriess. ! ! class Generation; ! class HeapRegion; class BufferingOopClosure: public OopClosure { protected: ! enum PrivateConstants { ! BufferLength = 1024 ! }; ! ! StarTask _buffer[BufferLength]; ! StarTask* _buffer_top; ! StarTask* _buffer_curr; OopClosure* _oc; double _closure_app_seconds; ! void process_buffer () { ! double start = os::elapsedTime(); ! for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) { ! if (curr->is_narrow()) { ! assert(UseCompressedOops, "Error"); ! _oc->do_oop((narrowOop*)(*curr)); ! } else { _oc->do_oop((oop*)(*curr)); } } ! _buffer_curr = _buffer; _closure_app_seconds += (os::elapsedTime() - start); } ! template <class T> inline void do_oop_work(T* p) { ! if (_buffer_curr == _buffer_top) { process_buffer(); } ! StarTask new_ref(p); ! *_buffer_curr = new_ref; ! ++_buffer_curr; } public: ! virtual void do_oop(narrowOop* p) { do_oop_work(p); } ! virtual void do_oop(oop* p) { do_oop_work(p); } ! void done () { ! if (_buffer_curr > _buffer) { process_buffer(); } } ! double closure_app_seconds () { return _closure_app_seconds; } ! BufferingOopClosure (OopClosure *oc) : _oc(oc), ! _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength), _closure_app_seconds(0.0) { } }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP --- 23,139 ---- */ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP ! #include "memory/iterator.hpp" #include "runtime/os.hpp" ! #include "utilities/debug.hpp" // A BufferingOops closure tries to separate out the cost of finding roots // from the cost of applying closures to them. It maintains an array of // ref-containing locations. Until the array is full, applying the closure // to an oop* merely records that location in the array. Since this // closure app cost is small, an elapsed timer can approximately attribute // all of this cost to the cost of finding the roots. When the array fills // up, the wrapped closure is applied to all elements, keeping track of // this elapsed time of this process, and leaving the array empty. // The caller must be sure to call "done" to process any unprocessed ! // buffered entries. class BufferingOopClosure: public OopClosure { + friend class TestBufferingOopClosure; protected: ! static const size_t BufferLength = 1024; ! ! // The full-sized oops are filled in from the bottom, ! // while the narrowOops are filled in from the top. ! void* _buffer[BufferLength]; ! void** _oop_top; ! void** _narrowOop_bottom; OopClosure* _oc; double _closure_app_seconds; ! ! bool is_buffer_empty() { ! return _oop_top == _buffer && _narrowOop_bottom == (_buffer + BufferLength - 1); ! } ! ! bool is_buffer_full() { ! return (uintptr_t)_narrowOop_bottom < (uintptr_t)_oop_top; ! } ! ! // Process addresses containing full-sized oops. ! void process_oops() { ! for (void** curr = _buffer; curr < _oop_top; ++curr) { _oc->do_oop((oop*)(*curr)); } + _oop_top = _buffer; + } + + // Process addresses containing narrow oops. + void process_narrowOops() { + for (void** curr = _buffer + BufferLength - 1; curr > _narrowOop_bottom; --curr) { + _oc->do_oop((narrowOop*)(*curr)); + } + _narrowOop_bottom = _buffer + BufferLength - 1; } ! ! // Apply the closure to all oops and clear the buffer. ! // Accumulate the time it took. ! void process_buffer() { ! double start = os::elapsedTime(); ! ! process_oops(); ! process_narrowOops(); ! _closure_app_seconds += (os::elapsedTime() - start); } ! void process_buffer_if_full() { ! if (is_buffer_full()) { process_buffer(); } ! } ! ! void add_narrowOop(narrowOop* p) { ! assert(!is_buffer_full(), "Buffer should not be full"); ! *_narrowOop_bottom = (void*)p; ! _narrowOop_bottom--; ! } ! ! void add_oop(oop* p) { ! assert(!is_buffer_full(), "Buffer should not be full"); ! *_oop_top = (void*)p; ! _oop_top++; } public: ! virtual void do_oop(narrowOop* p) { ! process_buffer_if_full(); ! add_narrowOop(p); ! } ! ! virtual void do_oop(oop* p) { ! process_buffer_if_full(); ! add_oop(p); ! } ! void done() { ! if (!is_buffer_empty()) { process_buffer(); } } ! ! double closure_app_seconds() { return _closure_app_seconds; } ! ! BufferingOopClosure(OopClosure *oc) : _oc(oc), ! _oop_top(_buffer), ! _narrowOop_bottom(_buffer + BufferLength - 1), _closure_app_seconds(0.0) { } }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP