sla@5237: /* sla@5237: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. sla@5237: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. sla@5237: * sla@5237: * This code is free software; you can redistribute it and/or modify it sla@5237: * under the terms of the GNU General Public License version 2 only, as sla@5237: * published by the Free Software Foundation. sla@5237: * sla@5237: * This code is distributed in the hope that it will be useful, but WITHOUT sla@5237: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or sla@5237: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License sla@5237: * version 2 for more details (a copy is included in the LICENSE file that sla@5237: * accompanied this code). sla@5237: * sla@5237: * You should have received a copy of the GNU General Public License version sla@5237: * 2 along with this work; if not, write to the Free Software Foundation, sla@5237: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. sla@5237: * sla@5237: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA sla@5237: * or visit www.oracle.com if you need additional information or have any sla@5237: * questions. sla@5237: * sla@5237: */ sla@5237: sla@5237: #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP sla@5237: #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP sla@5237: sla@5237: #include "memory/allocation.hpp" sla@5237: #include "prims/jni_md.h" sla@5237: #include "utilities/macros.hpp" mgronlun@6131: #include "utilities/ticks.hpp" sla@5237: sla@5237: class ConcurrentPhase; sla@5237: class GCPhase; sla@5237: class PausePhase; sla@5237: sla@5237: template class GrowableArray; sla@5237: sla@5237: class PhaseVisitor { sla@5237: public: sla@5237: virtual void visit(GCPhase* phase) = 0; sla@5237: virtual void visit(PausePhase* phase) { visit((GCPhase*)phase); } sla@5237: virtual void visit(ConcurrentPhase* phase) { visit((GCPhase*)phase); } sla@5237: }; sla@5237: sla@5237: class GCPhase { sla@5237: const char* _name; sla@5237: int _level; mgronlun@6131: Ticks _start; mgronlun@6131: Ticks _end; sla@5237: sla@5237: public: sla@5237: void set_name(const char* name) { _name = name; } mgronlun@6131: const char* name() const { return _name; } sla@5237: mgronlun@6131: int level() const { return _level; } sla@5237: void set_level(int level) { _level = level; } sla@5237: mgronlun@6131: const Ticks start() const { return _start; } mgronlun@6131: void set_start(const Ticks& time) { _start = time; } sla@5237: mgronlun@6131: const Ticks end() const { return _end; } mgronlun@6131: void set_end(const Ticks& time) { _end = time; } sla@5237: sla@5237: virtual void accept(PhaseVisitor* visitor) = 0; sla@5237: }; sla@5237: sla@5237: class PausePhase : public GCPhase { sla@5237: public: sla@5237: void accept(PhaseVisitor* visitor) { sla@5237: visitor->visit(this); sla@5237: } sla@5237: }; sla@5237: sla@5237: class ConcurrentPhase : public GCPhase { sla@5237: void accept(PhaseVisitor* visitor) { sla@5237: visitor->visit(this); sla@5237: } sla@5237: }; sla@5237: sla@5237: class PhasesStack { sla@5237: public: sla@5237: // FIXME: Temporary set to 5 (used to be 4), since Reference processing needs it. sla@5237: static const int PHASE_LEVELS = 5; sla@5237: sla@5237: private: sla@5237: int _phase_indices[PHASE_LEVELS]; sla@5237: int _next_phase_level; sla@5237: sla@5237: public: sla@5237: PhasesStack() { clear(); } sla@5237: void clear(); sla@5237: sla@5237: void push(int phase_index); sla@5237: int pop(); sla@5237: int count() const; sla@5237: }; sla@5237: sla@5237: class TimePartitions { sla@5237: static const int INITIAL_CAPACITY = 10; sla@5237: sla@5237: // Currently we only support pause phases. sla@5237: GrowableArray* _phases; sla@5237: PhasesStack _active_phases; sla@5237: mgronlun@6131: Tickspan _sum_of_pauses; mgronlun@6131: Tickspan _longest_pause; sla@5237: sla@5237: public: sla@5237: TimePartitions(); sla@5237: ~TimePartitions(); sla@5237: void clear(); sla@5237: mgronlun@6131: void report_gc_phase_start(const char* name, const Ticks& time); mgronlun@6131: void report_gc_phase_end(const Ticks& time); sla@5237: sla@5237: int num_phases() const; sla@5237: GCPhase* phase_at(int index) const; sla@5237: mgronlun@6131: const Tickspan sum_of_pauses() const { return _sum_of_pauses; } mgronlun@6131: const Tickspan longest_pause() const { return _longest_pause; } sla@5237: sla@5237: bool has_active_phases(); sla@5237: private: sla@5237: void update_statistics(GCPhase* phase); sla@5237: }; sla@5237: sla@5237: class PhasesIterator { sla@5237: public: sla@5237: virtual bool has_next() = 0; sla@5237: virtual GCPhase* next() = 0; sla@5237: }; sla@5237: sla@5237: class GCTimer : public ResourceObj { sla@5237: NOT_PRODUCT(friend class GCTimerTest;) sla@5237: protected: mgronlun@6131: Ticks _gc_start; mgronlun@6131: Ticks _gc_end; sla@5237: TimePartitions _time_partitions; sla@5237: sla@5237: public: mgronlun@6131: virtual void register_gc_start(const Ticks& time = Ticks::now()); mgronlun@6131: virtual void register_gc_end(const Ticks& time = Ticks::now()); sla@5237: mgronlun@6131: void register_gc_phase_start(const char* name, const Ticks& time); mgronlun@6131: void register_gc_phase_end(const Ticks& time); sla@5237: mgronlun@6131: const Ticks gc_start() const { return _gc_start; } mgronlun@6131: const Ticks gc_end() const { return _gc_end; } sla@5237: sla@5237: TimePartitions* time_partitions() { return &_time_partitions; } sla@5237: sla@5237: protected: mgronlun@6131: void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now()); mgronlun@6131: void register_gc_pause_end(const Ticks& time = Ticks::now()); sla@5237: }; sla@5237: sla@5237: class STWGCTimer : public GCTimer { sla@5237: public: mgronlun@6131: virtual void register_gc_start(const Ticks& time = Ticks::now()); mgronlun@6131: virtual void register_gc_end(const Ticks& time = Ticks::now()); sla@5237: }; sla@5237: sla@5237: class ConcurrentGCTimer : public GCTimer { sla@5237: public: mgronlun@6131: void register_gc_pause_start(const char* name); mgronlun@6131: void register_gc_pause_end(); sla@5237: }; sla@5237: sla@5237: class TimePartitionPhasesIterator { sla@5237: TimePartitions* _time_partitions; sla@5237: int _next; sla@5237: sla@5237: public: sla@5237: TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { } sla@5237: sla@5237: virtual bool has_next(); sla@5237: virtual GCPhase* next(); sla@5237: }; sla@5237: sla@5237: sla@5237: /////////////// Unit tests /////////////// sla@5237: sla@5237: #ifndef PRODUCT sla@5237: sla@5237: class GCTimerAllTest { sla@5237: public: sla@5237: static void all(); sla@5237: }; sla@5237: sla@5237: #endif sla@5237: sla@5237: #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP