Mercurial > hg > graal-compiler
annotate src/share/vm/utilities/events.cpp @ 1662:e0ba4e04c839
6969574: invokedynamic call sites deoptimize instead of executing
Reviewed-by: kvn
author | jrose |
---|---|
date | Fri, 16 Jul 2010 18:14:19 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 1997, 2006, 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 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_events.cpp.incl" | |
27 | |
28 | |
29 #ifndef PRODUCT | |
30 | |
31 //////////////////////////////////////////////////////////////////////////// | |
32 // Event | |
33 | |
34 typedef u4 EventID; | |
35 | |
36 class Event VALUE_OBJ_CLASS_SPEC { | |
37 private: | |
38 jlong _time_tick; | |
39 intx _thread_id; | |
40 const char* _format; | |
41 int _indent; | |
42 intptr_t _arg_1; | |
43 intptr_t _arg_2; | |
44 intptr_t _arg_3; | |
45 | |
46 // only EventBuffer::add_event() can assign event id | |
47 friend class EventBuffer; | |
48 EventID _id; | |
49 | |
50 public: | |
51 | |
52 void clear() { _format = NULL; } | |
53 | |
54 EventID id() const { return _id; } | |
55 | |
56 void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { | |
57 _format = format; | |
58 _arg_1 = arg_1; | |
59 _arg_2 = arg_2; | |
60 _arg_3 = arg_3; | |
61 | |
62 _indent = indent; | |
63 | |
64 _thread_id = os::current_thread_id(); | |
65 _time_tick = os::elapsed_counter(); | |
66 } | |
67 | |
68 void print_on(outputStream *st) { | |
69 if (_format == NULL) return; | |
70 st->print(" %d", _thread_id); | |
71 st->print(" %3.2g ", (double)_time_tick / os::elapsed_frequency()); | |
72 st->fill_to(20); | |
73 for (int index = 0; index < _indent; index++) { | |
74 st->print("| "); | |
75 } | |
76 st->print_cr(_format, _arg_1, _arg_2, _arg_3); | |
77 } | |
78 }; | |
79 | |
80 //////////////////////////////////////////////////////////////////////////// | |
81 // EventBuffer | |
82 // | |
83 // Simple lock-free event queue. Every event has a unique 32-bit id. | |
84 // It's fine if two threads add events at the same time, because they | |
85 // will get different event id, and then write to different buffer location. | |
86 // However, it is assumed that add_event() is quick enough (or buffer size | |
87 // is big enough), so when one thread is adding event, there can't be more | |
88 // than "size" events created by other threads; otherwise we'll end up having | |
89 // two threads writing to the same location. | |
90 | |
91 class EventBuffer : AllStatic { | |
92 private: | |
93 static Event* buffer; | |
94 static int size; | |
95 static jint indent; | |
96 static volatile EventID _current_event_id; | |
97 | |
98 static EventID get_next_event_id() { | |
99 return (EventID)Atomic::add(1, (jint*)&_current_event_id); | |
100 } | |
101 | |
102 public: | |
103 static void inc_indent() { Atomic::inc(&indent); } | |
104 static void dec_indent() { Atomic::dec(&indent); } | |
105 | |
106 static bool get_event(EventID id, Event* event) { | |
107 int index = (int)(id % size); | |
108 if (buffer[index].id() == id) { | |
109 memcpy(event, &buffer[index], sizeof(Event)); | |
110 // check id again; if buffer[index] is being updated by another thread, | |
111 // event->id() will contain different value. | |
112 return (event->id() == id); | |
113 } else { | |
114 // id does not match - id is invalid, or event is overwritten | |
115 return false; | |
116 } | |
117 } | |
118 | |
119 // add a new event to the queue; if EventBuffer is full, this call will | |
120 // overwrite the oldest event in the queue | |
121 static EventID add_event(const char* format, | |
122 intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { | |
123 // assign a unique id | |
124 EventID id = get_next_event_id(); | |
125 | |
126 // event will be copied to buffer[index] | |
127 int index = (int)(id % size); | |
128 | |
129 // first, invalidate id, buffer[index] can't have event with id = index + 2 | |
130 buffer[index]._id = index + 2; | |
131 | |
132 // make sure everyone has seen that buffer[index] is invalid | |
133 OrderAccess::fence(); | |
134 | |
135 // ... before updating its value | |
136 buffer[index].fill(indent, format, arg_1, arg_2, arg_3); | |
137 | |
138 // finally, set up real event id, now buffer[index] contains valid event | |
139 OrderAccess::release_store(&(buffer[index]._id), id); | |
140 | |
141 return id; | |
142 } | |
143 | |
144 static void print_last(outputStream *st, int number) { | |
145 st->print_cr("[Last %d events in the event buffer]", number); | |
146 st->print_cr("-<thd>-<elapsed sec>-<description>---------------------"); | |
147 | |
148 int count = 0; | |
149 EventID id = _current_event_id; | |
150 while (count < number) { | |
151 Event event; | |
152 if (get_event(id, &event)) { | |
153 event.print_on(st); | |
154 } | |
155 id--; | |
156 count++; | |
157 } | |
158 } | |
159 | |
160 static void print_all(outputStream* st) { | |
161 print_last(st, size); | |
162 } | |
163 | |
164 static void init() { | |
165 // Allocate the event buffer | |
166 size = EventLogLength; | |
167 buffer = NEW_C_HEAP_ARRAY(Event, size); | |
168 | |
169 _current_event_id = 0; | |
170 | |
171 // Clear the event buffer | |
172 for (int index = 0; index < size; index++) { | |
173 buffer[index]._id = index + 1; // index + 1 is invalid id | |
174 buffer[index].clear(); | |
175 } | |
176 } | |
177 }; | |
178 | |
179 Event* EventBuffer::buffer; | |
180 int EventBuffer::size; | |
181 volatile EventID EventBuffer::_current_event_id; | |
182 int EventBuffer::indent; | |
183 | |
184 //////////////////////////////////////////////////////////////////////////// | |
185 // Events | |
186 | |
187 // Events::log() is safe for signal handlers | |
188 void Events::log(const char* format, ...) { | |
189 if (LogEvents) { | |
190 va_list ap; | |
191 va_start(ap, format); | |
192 intptr_t arg_1 = va_arg(ap, intptr_t); | |
193 intptr_t arg_2 = va_arg(ap, intptr_t); | |
194 intptr_t arg_3 = va_arg(ap, intptr_t); | |
195 va_end(ap); | |
196 | |
197 EventBuffer::add_event(format, arg_1, arg_2, arg_3); | |
198 } | |
199 } | |
200 | |
201 void Events::print_all(outputStream *st) { | |
202 EventBuffer::print_all(st); | |
203 } | |
204 | |
205 void Events::print_last(outputStream *st, int number) { | |
206 EventBuffer::print_last(st, number); | |
207 } | |
208 | |
209 /////////////////////////////////////////////////////////////////////////// | |
210 // EventMark | |
211 | |
212 EventMark::EventMark(const char* format, ...) { | |
213 if (LogEvents) { | |
214 va_list ap; | |
215 va_start(ap, format); | |
216 intptr_t arg_1 = va_arg(ap, intptr_t); | |
217 intptr_t arg_2 = va_arg(ap, intptr_t); | |
218 intptr_t arg_3 = va_arg(ap, intptr_t); | |
219 va_end(ap); | |
220 | |
221 EventBuffer::add_event(format, arg_1, arg_2, arg_3); | |
222 EventBuffer::inc_indent(); | |
223 } | |
224 } | |
225 | |
226 EventMark::~EventMark() { | |
227 if (LogEvents) { | |
228 EventBuffer::dec_indent(); | |
229 EventBuffer::add_event("done", 0, 0, 0); | |
230 } | |
231 } | |
232 | |
233 /////////////////////////////////////////////////////////////////////////// | |
234 | |
235 void eventlog_init() { | |
236 EventBuffer::init(); | |
237 } | |
238 | |
239 int print_all_events(outputStream *st) { | |
240 EventBuffer::print_all(st); | |
241 return 1; | |
242 } | |
243 | |
244 #else | |
245 | |
246 void eventlog_init() {} | |
247 int print_all_events(outputStream *st) { return 0; } | |
248 | |
249 #endif // PRODUCT |