Mercurial > hg > graal-compiler
annotate src/share/vm/prims/jvmtiEnvThreadState.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | f95d63e2154a |
children | d2a62e0f25eb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2003, 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 "classfile/systemDictionary.hpp" | |
27 #include "interpreter/interpreter.hpp" | |
28 #include "jvmtifiles/jvmtiEnv.hpp" | |
29 #include "memory/resourceArea.hpp" | |
30 #include "prims/jvmtiEnvThreadState.hpp" | |
31 #include "prims/jvmtiEventController.inline.hpp" | |
32 #include "prims/jvmtiImpl.hpp" | |
33 #include "runtime/handles.hpp" | |
34 #include "runtime/handles.inline.hpp" | |
35 #include "runtime/interfaceSupport.hpp" | |
36 #include "runtime/javaCalls.hpp" | |
37 #include "runtime/signature.hpp" | |
38 #include "runtime/vframe.hpp" | |
39 #include "runtime/vm_operations.hpp" | |
0 | 40 |
41 | |
42 /////////////////////////////////////////////////////////////// | |
43 // | |
44 // class JvmtiFramePop | |
45 // | |
46 | |
47 #ifndef PRODUCT | |
48 void JvmtiFramePop::print() { | |
49 tty->print_cr("_frame_number=%d", _frame_number); | |
50 } | |
51 #endif | |
52 | |
53 | |
54 /////////////////////////////////////////////////////////////// | |
55 // | |
56 // class JvmtiFramePops - private methods | |
57 // | |
58 | |
59 void | |
60 JvmtiFramePops::set(JvmtiFramePop& fp) { | |
61 if (_pops->find(fp.frame_number()) < 0) { | |
62 _pops->append(fp.frame_number()); | |
63 } | |
64 } | |
65 | |
66 | |
67 void | |
68 JvmtiFramePops::clear(JvmtiFramePop& fp) { | |
69 assert(_pops->length() > 0, "No more frame pops"); | |
70 | |
71 _pops->remove(fp.frame_number()); | |
72 } | |
73 | |
74 | |
75 int | |
76 JvmtiFramePops::clear_to(JvmtiFramePop& fp) { | |
77 int cleared = 0; | |
78 int index = 0; | |
79 while (index < _pops->length()) { | |
80 JvmtiFramePop pop = JvmtiFramePop(_pops->at(index)); | |
81 if (pop.above_on_stack(fp)) { | |
82 _pops->remove_at(index); | |
83 ++cleared; | |
84 } else { | |
85 ++index; | |
86 } | |
87 } | |
88 return cleared; | |
89 } | |
90 | |
91 | |
92 /////////////////////////////////////////////////////////////// | |
93 // | |
94 // class JvmtiFramePops - public methods | |
95 // | |
96 | |
97 JvmtiFramePops::JvmtiFramePops() { | |
98 _pops = new (ResourceObj::C_HEAP) GrowableArray<int> (2, true); | |
99 } | |
100 | |
101 JvmtiFramePops::~JvmtiFramePops() { | |
102 // return memory to c_heap. | |
103 delete _pops; | |
104 } | |
105 | |
106 | |
107 #ifndef PRODUCT | |
108 void JvmtiFramePops::print() { | |
109 ResourceMark rm; | |
110 | |
111 int n = _pops->length(); | |
112 for (int i=0; i<n; i++) { | |
113 JvmtiFramePop fp = JvmtiFramePop(_pops->at(i)); | |
114 tty->print("%d: ", i); | |
115 fp.print(); | |
116 tty->print_cr(""); | |
117 } | |
118 } | |
119 #endif | |
120 | |
121 /////////////////////////////////////////////////////////////// | |
122 // | |
123 // class JvmtiEnvThreadState | |
124 // | |
125 // Instances of JvmtiEnvThreadState hang off of each JvmtiThreadState, | |
126 // one per JvmtiEnv. | |
127 // | |
128 | |
129 JvmtiEnvThreadState::JvmtiEnvThreadState(JavaThread *thread, JvmtiEnvBase *env) : | |
130 _event_enable() { | |
131 _thread = thread; | |
132 _env = (JvmtiEnv*)env; | |
133 _next = NULL; | |
134 _frame_pops = NULL; | |
135 _current_bci = 0; | |
136 _current_method_id = NULL; | |
137 _breakpoint_posted = false; | |
138 _single_stepping_posted = false; | |
139 _agent_thread_local_storage_data = NULL; | |
140 } | |
141 | |
142 JvmtiEnvThreadState::~JvmtiEnvThreadState() { | |
143 delete _frame_pops; | |
144 _frame_pops = NULL; | |
145 } | |
146 | |
147 // Given that a new (potential) event has come in, | |
148 // maintain the current JVMTI location on a per-thread per-env basis | |
149 // and use it to filter out duplicate events: | |
150 // - instruction rewrites | |
151 // - breakpoint followed by single step | |
152 // - single step at a breakpoint | |
153 void JvmtiEnvThreadState::compare_and_set_current_location(methodOop new_method, | |
154 address new_location, jvmtiEvent event) { | |
155 | |
156 int new_bci = new_location - new_method->code_base(); | |
157 | |
158 // The method is identified and stored as a jmethodID which is safe in this | |
159 // case because the class cannot be unloaded while a method is executing. | |
160 jmethodID new_method_id = new_method->jmethod_id(); | |
161 | |
162 // the last breakpoint or single step was at this same location | |
163 if (_current_bci == new_bci && _current_method_id == new_method_id) { | |
164 switch (event) { | |
165 case JVMTI_EVENT_BREAKPOINT: | |
166 // Repeat breakpoint is complicated. If we previously posted a breakpoint | |
167 // event at this location and if we also single stepped at this location | |
168 // then we skip the duplicate breakpoint. | |
169 _breakpoint_posted = _breakpoint_posted && _single_stepping_posted; | |
170 break; | |
171 case JVMTI_EVENT_SINGLE_STEP: | |
172 // Repeat single step is easy: just don't post it again. | |
173 // If step is pending for popframe then it may not be | |
174 // a repeat step. The new_bci and method_id is same as current_bci | |
175 // and current method_id after pop and step for recursive calls. | |
176 // This has been handled by clearing the location | |
177 _single_stepping_posted = true; | |
178 break; | |
179 default: | |
180 assert(false, "invalid event value passed"); | |
181 break; | |
182 } | |
183 return; | |
184 } | |
185 | |
186 set_current_location(new_method_id, new_bci); | |
187 _breakpoint_posted = false; | |
188 _single_stepping_posted = false; | |
189 } | |
190 | |
191 | |
192 JvmtiFramePops* JvmtiEnvThreadState::get_frame_pops() { | |
193 #ifdef ASSERT | |
194 uint32_t debug_bits = 0; | |
195 #endif | |
196 assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), | |
197 "frame pop data only accessible from same thread or while suspended"); | |
198 | |
199 if (_frame_pops == NULL) { | |
200 _frame_pops = new JvmtiFramePops(); | |
201 assert(_frame_pops != NULL, "_frame_pops != NULL"); | |
202 } | |
203 return _frame_pops; | |
204 } | |
205 | |
206 | |
207 bool JvmtiEnvThreadState::has_frame_pops() { | |
208 return _frame_pops == NULL? false : (_frame_pops->length() > 0); | |
209 } | |
210 | |
211 void JvmtiEnvThreadState::set_frame_pop(int frame_number) { | |
212 #ifdef ASSERT | |
213 uint32_t debug_bits = 0; | |
214 #endif | |
215 assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), | |
216 "frame pop data only accessible from same thread or while suspended"); | |
217 JvmtiFramePop fpop(frame_number); | |
218 JvmtiEventController::set_frame_pop(this, fpop); | |
219 } | |
220 | |
221 | |
222 void JvmtiEnvThreadState::clear_frame_pop(int frame_number) { | |
223 #ifdef ASSERT | |
224 uint32_t debug_bits = 0; | |
225 #endif | |
226 assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), | |
227 "frame pop data only accessible from same thread or while suspended"); | |
228 JvmtiFramePop fpop(frame_number); | |
229 JvmtiEventController::clear_frame_pop(this, fpop); | |
230 } | |
231 | |
232 | |
233 void JvmtiEnvThreadState::clear_to_frame_pop(int frame_number) { | |
234 #ifdef ASSERT | |
235 uint32_t debug_bits = 0; | |
236 #endif | |
237 assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), | |
238 "frame pop data only accessible from same thread or while suspended"); | |
239 JvmtiFramePop fpop(frame_number); | |
240 JvmtiEventController::clear_to_frame_pop(this, fpop); | |
241 } | |
242 | |
243 | |
244 bool JvmtiEnvThreadState::is_frame_pop(int cur_frame_number) { | |
245 #ifdef ASSERT | |
246 uint32_t debug_bits = 0; | |
247 #endif | |
248 assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), | |
249 "frame pop data only accessible from same thread or while suspended"); | |
250 if (!get_thread()->is_interp_only_mode() || _frame_pops == NULL) { | |
251 return false; | |
252 } | |
253 JvmtiFramePop fp(cur_frame_number); | |
254 return get_frame_pops()->contains(fp); | |
255 } | |
256 | |
257 | |
258 class VM_GetCurrentLocation : public VM_Operation { | |
259 private: | |
260 JavaThread *_thread; | |
261 jmethodID _method_id; | |
262 int _bci; | |
263 | |
264 public: | |
265 VM_GetCurrentLocation(JavaThread *thread) { | |
266 _thread = thread; | |
267 } | |
268 VMOp_Type type() const { return VMOp_GetCurrentLocation; } | |
269 void doit() { | |
270 ResourceMark rmark; // _thread != Thread::current() | |
271 RegisterMap rm(_thread, false); | |
272 javaVFrame* vf = _thread->last_java_vframe(&rm); | |
273 assert(vf != NULL, "must have last java frame"); | |
274 methodOop method = vf->method(); | |
275 _method_id = method->jmethod_id(); | |
276 _bci = vf->bci(); | |
277 } | |
278 void get_current_location(jmethodID *method_id, int *bci) { | |
279 *method_id = _method_id; | |
280 *bci = _bci; | |
281 } | |
282 }; | |
283 | |
284 void JvmtiEnvThreadState::reset_current_location(jvmtiEvent event_type, bool enabled) { | |
285 assert(event_type == JVMTI_EVENT_SINGLE_STEP || event_type == JVMTI_EVENT_BREAKPOINT, | |
286 "must be single-step or breakpoint event"); | |
287 | |
288 // Current location is used to detect the following: | |
289 // 1) a breakpoint event followed by single-stepping to the same bci | |
290 // 2) single-step to a bytecode that will be transformed to a fast version | |
291 // We skip to avoid posting the duplicate single-stepping event. | |
292 | |
293 // If single-stepping is disabled, clear current location so that | |
294 // single-stepping to the same method and bcp at a later time will be | |
295 // detected if single-stepping is enabled at that time (see 4388912). | |
296 | |
297 // If single-stepping is enabled, set the current location to the | |
298 // current method and bcp. This covers the following type of case, | |
299 // e.g., the debugger stepi command: | |
300 // - bytecode single stepped | |
301 // - SINGLE_STEP event posted and SINGLE_STEP event disabled | |
302 // - SINGLE_STEP event reenabled | |
303 // - bytecode rewritten to fast version | |
304 | |
305 // If breakpoint event is disabled, clear current location only if | |
306 // single-stepping is not enabled. Otherwise, keep the thread location | |
307 // to detect any duplicate events. | |
308 | |
309 if (enabled) { | |
310 // If enabling breakpoint, no need to reset. | |
311 // Can't do anything if empty stack. | |
312 if (event_type == JVMTI_EVENT_SINGLE_STEP && _thread->has_last_Java_frame()) { | |
313 jmethodID method_id; | |
314 int bci; | |
315 // The java thread stack may not be walkable for a running thread | |
316 // so get current location at safepoint. | |
317 VM_GetCurrentLocation op(_thread); | |
318 VMThread::execute(&op); | |
319 op.get_current_location(&method_id, &bci); | |
320 set_current_location(method_id, bci); | |
321 } | |
322 } else if (event_type == JVMTI_EVENT_SINGLE_STEP || !is_enabled(JVMTI_EVENT_SINGLE_STEP)) { | |
323 // If this is to disable breakpoint, also check if single-step is not enabled | |
324 clear_current_location(); | |
325 } | |
326 } |