/* * Copyright (c) 2009, 2022, 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. *
*/
template <class E, MEMFLAGS F> void Stack<E, F>::push(E item)
{
assert(!is_full(), "pushing onto a full stack");
size_t index = this->_cur_seg_size; if (index == this->_seg_size) {
push_segment();
index = 0; // Instead of fetching known zero _cur_seg_size.
}
this->_cur_seg[index] = item;
this->_cur_seg_size = index + 1;
}
template <class E, MEMFLAGS F>
E Stack<E, F>::pop()
{
assert(!is_empty(), "popping from an empty stack"); // _cur_seg_size is never 0 if not empty. pop that empties a // segment also pops the segment. push that adds a segment always // adds an entry to the new segment.
assert(this->_cur_seg_size != 0, "invariant");
size_t index = --this->_cur_seg_size;
E result = _cur_seg[index]; if (index == 0) pop_segment(); return result;
}
template <class E, MEMFLAGS F> void Stack<E, F>::clear(bool clear_cache)
{
free_segments(_cur_seg); if (clear_cache) free_segments(_cache);
reset(clear_cache);
}
// Stack is used by the GC code and in some hot paths a lot of the Stack // code gets inlined. This is generally good, but when too much code has // been inlined, further inlining in the caller might be inhibited. So // prevent infrequent slow path segment manipulation from being inlined. template <class E, MEMFLAGS F>
NOINLINE void Stack<E, F>::push_segment()
{
assert(this->_cur_seg_size == this->_seg_size, "current segment is not full");
E* next; if (this->_cache_size > 0) { // Use a cached segment.
next = _cache;
_cache = get_link(_cache);
--this->_cache_size;
} else {
next = alloc(segment_bytes());
DEBUG_ONLY(zap_segment(next, true);)
} constbool at_empty_transition = is_empty();
this->_cur_seg = set_link(next, _cur_seg);
this->_cur_seg_size = 0;
this->_full_seg_size += at_empty_transition ? 0 : this->_seg_size;
DEBUG_ONLY(verify(at_empty_transition);)
}
template <class E, MEMFLAGS F>
NOINLINE void Stack<E, F>::pop_segment()
{
assert(this->_cur_seg_size == 0, "current segment is not empty");
E* const prev = get_link(_cur_seg); if (this->_cache_size < this->_max_cache_size) { // Add the current segment to the cache.
DEBUG_ONLY(zap_segment(_cur_seg, false);)
_cache = set_link(_cur_seg, _cache);
++this->_cache_size;
} else {
DEBUG_ONLY(zap_segment(_cur_seg, true);)
free(_cur_seg, segment_bytes());
} constbool at_empty_transition = prev == NULL;
this->_cur_seg = prev;
this->_cur_seg_size = this->_seg_size;
this->_full_seg_size -= at_empty_transition ? 0 : this->_seg_size;
DEBUG_ONLY(verify(at_empty_transition);)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.