Mercurial > hg > truffle
annotate src/share/vm/utilities/events.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | f08d439fab8c |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "runtime/mutexLocker.hpp" | |
28 #include "runtime/osThread.hpp" | |
29 #include "runtime/threadLocalStorage.hpp" | |
30 #include "runtime/timer.hpp" | |
31 #include "utilities/events.hpp" | |
32 #ifdef TARGET_OS_FAMILY_linux | |
33 # include "thread_linux.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_OS_FAMILY_solaris | |
36 # include "thread_solaris.inline.hpp" | |
37 #endif | |
38 #ifdef TARGET_OS_FAMILY_windows | |
39 # include "thread_windows.inline.hpp" | |
40 #endif | |
0 | 41 |
42 | |
43 #ifndef PRODUCT | |
44 | |
45 //////////////////////////////////////////////////////////////////////////// | |
46 // Event | |
47 | |
48 typedef u4 EventID; | |
49 | |
50 class Event VALUE_OBJ_CLASS_SPEC { | |
51 private: | |
52 jlong _time_tick; | |
53 intx _thread_id; | |
54 const char* _format; | |
55 int _indent; | |
56 intptr_t _arg_1; | |
57 intptr_t _arg_2; | |
58 intptr_t _arg_3; | |
59 | |
60 // only EventBuffer::add_event() can assign event id | |
61 friend class EventBuffer; | |
62 EventID _id; | |
63 | |
64 public: | |
65 | |
66 void clear() { _format = NULL; } | |
67 | |
68 EventID id() const { return _id; } | |
69 | |
70 void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { | |
71 _format = format; | |
72 _arg_1 = arg_1; | |
73 _arg_2 = arg_2; | |
74 _arg_3 = arg_3; | |
75 | |
76 _indent = indent; | |
77 | |
78 _thread_id = os::current_thread_id(); | |
79 _time_tick = os::elapsed_counter(); | |
80 } | |
81 | |
82 void print_on(outputStream *st) { | |
83 if (_format == NULL) return; | |
84 st->print(" %d", _thread_id); | |
85 st->print(" %3.2g ", (double)_time_tick / os::elapsed_frequency()); | |
86 st->fill_to(20); | |
87 for (int index = 0; index < _indent; index++) { | |
88 st->print("| "); | |
89 } | |
90 st->print_cr(_format, _arg_1, _arg_2, _arg_3); | |
91 } | |
92 }; | |
93 | |
94 //////////////////////////////////////////////////////////////////////////// | |
95 // EventBuffer | |
96 // | |
97 // Simple lock-free event queue. Every event has a unique 32-bit id. | |
98 // It's fine if two threads add events at the same time, because they | |
99 // will get different event id, and then write to different buffer location. | |
100 // However, it is assumed that add_event() is quick enough (or buffer size | |
101 // is big enough), so when one thread is adding event, there can't be more | |
102 // than "size" events created by other threads; otherwise we'll end up having | |
103 // two threads writing to the same location. | |
104 | |
105 class EventBuffer : AllStatic { | |
106 private: | |
107 static Event* buffer; | |
108 static int size; | |
109 static jint indent; | |
110 static volatile EventID _current_event_id; | |
111 | |
112 static EventID get_next_event_id() { | |
113 return (EventID)Atomic::add(1, (jint*)&_current_event_id); | |
114 } | |
115 | |
116 public: | |
117 static void inc_indent() { Atomic::inc(&indent); } | |
118 static void dec_indent() { Atomic::dec(&indent); } | |
119 | |
120 static bool get_event(EventID id, Event* event) { | |
121 int index = (int)(id % size); | |
122 if (buffer[index].id() == id) { | |
123 memcpy(event, &buffer[index], sizeof(Event)); | |
124 // check id again; if buffer[index] is being updated by another thread, | |
125 // event->id() will contain different value. | |
126 return (event->id() == id); | |
127 } else { | |
128 // id does not match - id is invalid, or event is overwritten | |
129 return false; | |
130 } | |
131 } | |
132 | |
133 // add a new event to the queue; if EventBuffer is full, this call will | |
134 // overwrite the oldest event in the queue | |
135 static EventID add_event(const char* format, | |
136 intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { | |
137 // assign a unique id | |
138 EventID id = get_next_event_id(); | |
139 | |
140 // event will be copied to buffer[index] | |
141 int index = (int)(id % size); | |
142 | |
143 // first, invalidate id, buffer[index] can't have event with id = index + 2 | |
144 buffer[index]._id = index + 2; | |
145 | |
146 // make sure everyone has seen that buffer[index] is invalid | |
147 OrderAccess::fence(); | |
148 | |
149 // ... before updating its value | |
150 buffer[index].fill(indent, format, arg_1, arg_2, arg_3); | |
151 | |
152 // finally, set up real event id, now buffer[index] contains valid event | |
153 OrderAccess::release_store(&(buffer[index]._id), id); | |
154 | |
155 return id; | |
156 } | |
157 | |
158 static void print_last(outputStream *st, int number) { | |
159 st->print_cr("[Last %d events in the event buffer]", number); | |
160 st->print_cr("-<thd>-<elapsed sec>-<description>---------------------"); | |
161 | |
162 int count = 0; | |
163 EventID id = _current_event_id; | |
164 while (count < number) { | |
165 Event event; | |
166 if (get_event(id, &event)) { | |
167 event.print_on(st); | |
168 } | |
169 id--; | |
170 count++; | |
171 } | |
172 } | |
173 | |
174 static void print_all(outputStream* st) { | |
175 print_last(st, size); | |
176 } | |
177 | |
178 static void init() { | |
179 // Allocate the event buffer | |
180 size = EventLogLength; | |
181 buffer = NEW_C_HEAP_ARRAY(Event, size); | |
182 | |
183 _current_event_id = 0; | |
184 | |
185 // Clear the event buffer | |
186 for (int index = 0; index < size; index++) { | |
187 buffer[index]._id = index + 1; // index + 1 is invalid id | |
188 buffer[index].clear(); | |
189 } | |
190 } | |
191 }; | |
192 | |
193 Event* EventBuffer::buffer; | |
194 int EventBuffer::size; | |
195 volatile EventID EventBuffer::_current_event_id; | |
196 int EventBuffer::indent; | |
197 | |
198 //////////////////////////////////////////////////////////////////////////// | |
199 // Events | |
200 | |
201 // Events::log() is safe for signal handlers | |
202 void Events::log(const char* format, ...) { | |
203 if (LogEvents) { | |
204 va_list ap; | |
205 va_start(ap, format); | |
206 intptr_t arg_1 = va_arg(ap, intptr_t); | |
207 intptr_t arg_2 = va_arg(ap, intptr_t); | |
208 intptr_t arg_3 = va_arg(ap, intptr_t); | |
209 va_end(ap); | |
210 | |
211 EventBuffer::add_event(format, arg_1, arg_2, arg_3); | |
212 } | |
213 } | |
214 | |
215 void Events::print_all(outputStream *st) { | |
216 EventBuffer::print_all(st); | |
217 } | |
218 | |
219 void Events::print_last(outputStream *st, int number) { | |
220 EventBuffer::print_last(st, number); | |
221 } | |
222 | |
223 /////////////////////////////////////////////////////////////////////////// | |
224 // EventMark | |
225 | |
226 EventMark::EventMark(const char* format, ...) { | |
227 if (LogEvents) { | |
228 va_list ap; | |
229 va_start(ap, format); | |
230 intptr_t arg_1 = va_arg(ap, intptr_t); | |
231 intptr_t arg_2 = va_arg(ap, intptr_t); | |
232 intptr_t arg_3 = va_arg(ap, intptr_t); | |
233 va_end(ap); | |
234 | |
235 EventBuffer::add_event(format, arg_1, arg_2, arg_3); | |
236 EventBuffer::inc_indent(); | |
237 } | |
238 } | |
239 | |
240 EventMark::~EventMark() { | |
241 if (LogEvents) { | |
242 EventBuffer::dec_indent(); | |
243 EventBuffer::add_event("done", 0, 0, 0); | |
244 } | |
245 } | |
246 | |
247 /////////////////////////////////////////////////////////////////////////// | |
248 | |
249 void eventlog_init() { | |
250 EventBuffer::init(); | |
251 } | |
252 | |
253 int print_all_events(outputStream *st) { | |
254 EventBuffer::print_all(st); | |
255 return 1; | |
256 } | |
257 | |
258 #else | |
259 | |
260 void eventlog_init() {} | |
261 int print_all_events(outputStream *st) { return 0; } | |
262 | |
263 #endif // PRODUCT |