Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/vframe_hp.cpp @ 3979:4dfb2df418f2
6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author | johnc |
---|---|
date | Thu, 22 Sep 2011 10:57:37 -0700 |
parents | 09b4dd4f152b |
children | 06f017f7daa7 d2a62e0f25eb |
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:
903
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
903
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:
903
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "code/codeCache.hpp" | |
27 #include "code/debugInfoRec.hpp" | |
28 #include "code/nmethod.hpp" | |
29 #include "code/pcDesc.hpp" | |
30 #include "code/scopeDesc.hpp" | |
31 #include "interpreter/interpreter.hpp" | |
32 #include "interpreter/oopMapCache.hpp" | |
33 #include "oops/instanceKlass.hpp" | |
34 #include "oops/oop.inline.hpp" | |
35 #include "runtime/basicLock.hpp" | |
36 #include "runtime/handles.inline.hpp" | |
37 #include "runtime/monitorChunk.hpp" | |
38 #include "runtime/signature.hpp" | |
39 #include "runtime/stubRoutines.hpp" | |
40 #include "runtime/vframeArray.hpp" | |
41 #include "runtime/vframe_hp.hpp" | |
42 #ifdef COMPILER2 | |
43 #include "opto/matcher.hpp" | |
44 #endif | |
0 | 45 |
46 | |
47 // ------------- compiledVFrame -------------- | |
48 | |
49 StackValueCollection* compiledVFrame::locals() const { | |
50 // Natives has no scope | |
51 if (scope() == NULL) return new StackValueCollection(0); | |
52 GrowableArray<ScopeValue*>* scv_list = scope()->locals(); | |
53 if (scv_list == NULL) return new StackValueCollection(0); | |
54 | |
55 // scv_list is the list of ScopeValues describing the JVM stack state. | |
56 // There is one scv_list entry for every JVM stack state in use. | |
57 int length = scv_list->length(); | |
58 StackValueCollection* result = new StackValueCollection(length); | |
59 // In rare instances set_locals may have occurred in which case | |
60 // there are local values that are not described by the ScopeValue anymore | |
61 GrowableArray<jvmtiDeferredLocalVariable*>* deferred = NULL; | |
62 GrowableArray<jvmtiDeferredLocalVariableSet*>* list = thread()->deferred_locals(); | |
63 if (list != NULL ) { | |
64 // In real life this never happens or is typically a single element search | |
65 for (int i = 0; i < list->length(); i++) { | |
66 if (list->at(i)->matches((vframe*)this)) { | |
67 deferred = list->at(i)->locals(); | |
68 break; | |
69 } | |
70 } | |
71 } | |
72 | |
73 for( int i = 0; i < length; i++ ) { | |
74 result->add( create_stack_value(scv_list->at(i)) ); | |
75 } | |
76 | |
77 // Replace specified locals with any deferred writes that are present | |
78 if (deferred != NULL) { | |
79 for ( int l = 0; l < deferred->length() ; l ++) { | |
80 jvmtiDeferredLocalVariable* val = deferred->at(l); | |
81 switch (val->type()) { | |
82 case T_BOOLEAN: | |
83 result->set_int_at(val->index(), val->value().z); | |
84 break; | |
85 case T_CHAR: | |
86 result->set_int_at(val->index(), val->value().c); | |
87 break; | |
88 case T_FLOAT: | |
89 result->set_float_at(val->index(), val->value().f); | |
90 break; | |
91 case T_DOUBLE: | |
92 result->set_double_at(val->index(), val->value().d); | |
93 break; | |
94 case T_BYTE: | |
95 result->set_int_at(val->index(), val->value().b); | |
96 break; | |
97 case T_SHORT: | |
98 result->set_int_at(val->index(), val->value().s); | |
99 break; | |
100 case T_INT: | |
101 result->set_int_at(val->index(), val->value().i); | |
102 break; | |
103 case T_LONG: | |
104 result->set_long_at(val->index(), val->value().j); | |
105 break; | |
106 case T_OBJECT: | |
107 { | |
108 Handle obj((oop)val->value().l); | |
109 result->set_obj_at(val->index(), obj); | |
110 } | |
111 break; | |
112 default: | |
113 ShouldNotReachHere(); | |
114 } | |
115 } | |
116 } | |
117 | |
118 return result; | |
119 } | |
120 | |
121 | |
122 void compiledVFrame::set_locals(StackValueCollection* values) const { | |
123 | |
124 fatal("Should use update_local for each local update"); | |
125 } | |
126 | |
127 void compiledVFrame::update_local(BasicType type, int index, jvalue value) { | |
128 | |
129 #ifdef ASSERT | |
130 | |
131 assert(fr().is_deoptimized_frame(), "frame must be scheduled for deoptimization"); | |
132 #endif /* ASSERT */ | |
133 GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = thread()->deferred_locals(); | |
134 if (deferred != NULL ) { | |
135 // See if this vframe has already had locals with deferred writes | |
136 int f; | |
137 for ( f = 0 ; f < deferred->length() ; f++ ) { | |
138 if (deferred->at(f)->matches(this)) { | |
139 // Matching, vframe now see if the local already had deferred write | |
140 GrowableArray<jvmtiDeferredLocalVariable*>* locals = deferred->at(f)->locals(); | |
141 int l; | |
142 for (l = 0 ; l < locals->length() ; l++ ) { | |
143 if (locals->at(l)->index() == index) { | |
144 locals->at(l)->set_value(value); | |
145 return; | |
146 } | |
147 } | |
148 // No matching local already present. Push a new value onto the deferred collection | |
149 locals->push(new jvmtiDeferredLocalVariable(index, type, value)); | |
150 return; | |
151 } | |
152 } | |
153 // No matching vframe must push a new vframe | |
154 } else { | |
155 // No deferred updates pending for this thread. | |
156 // allocate in C heap | |
157 deferred = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true); | |
158 thread()->set_deferred_locals(deferred); | |
159 } | |
160 deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id())); | |
161 assert(deferred->top()->id() == fr().id(), "Huh? Must match"); | |
162 deferred->top()->set_local_at(index, type, value); | |
163 } | |
164 | |
165 StackValueCollection* compiledVFrame::expressions() const { | |
166 // Natives has no scope | |
167 if (scope() == NULL) return new StackValueCollection(0); | |
168 GrowableArray<ScopeValue*>* scv_list = scope()->expressions(); | |
169 if (scv_list == NULL) return new StackValueCollection(0); | |
170 | |
171 // scv_list is the list of ScopeValues describing the JVM stack state. | |
172 // There is one scv_list entry for every JVM stack state in use. | |
173 int length = scv_list->length(); | |
174 StackValueCollection* result = new StackValueCollection(length); | |
175 for( int i = 0; i < length; i++ ) | |
176 result->add( create_stack_value(scv_list->at(i)) ); | |
177 | |
178 return result; | |
179 } | |
180 | |
181 | |
182 // The implementation of the following two methods was factorized into the | |
183 // class StackValue because it is also used from within deoptimization.cpp for | |
184 // rematerialization and relocking of non-escaping objects. | |
185 | |
186 StackValue *compiledVFrame::create_stack_value(ScopeValue *sv) const { | |
187 return StackValue::create_stack_value(&_fr, register_map(), sv); | |
188 } | |
189 | |
190 BasicLock* compiledVFrame::resolve_monitor_lock(Location location) const { | |
191 return StackValue::resolve_monitor_lock(&_fr, location); | |
192 } | |
193 | |
194 | |
195 GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const { | |
196 // Natives has no scope | |
197 if (scope() == NULL) { | |
198 nmethod* nm = code(); | |
199 methodOop method = nm->method(); | |
200 assert(method->is_native(), ""); | |
201 if (!method->is_synchronized()) { | |
202 return new GrowableArray<MonitorInfo*>(0); | |
203 } | |
204 // This monitor is really only needed for UseBiasedLocking, but | |
205 // return it in all cases for now as it might be useful for stack | |
206 // traces and tools as well | |
207 GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1); | |
208 // Casting away const | |
209 frame& fr = (frame&) _fr; | |
2019 | 210 MonitorInfo* info = new MonitorInfo( |
211 fr.get_native_receiver(), fr.get_native_monitor(), false, false); | |
0 | 212 monitors->push(info); |
213 return monitors; | |
214 } | |
215 GrowableArray<MonitorValue*>* monitors = scope()->monitors(); | |
216 if (monitors == NULL) { | |
217 return new GrowableArray<MonitorInfo*>(0); | |
218 } | |
219 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(monitors->length()); | |
220 for (int index = 0; index < monitors->length(); index++) { | |
221 MonitorValue* mv = monitors->at(index); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
222 ScopeValue* ov = mv->owner(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
223 StackValue *owner_sv = create_stack_value(ov); // it is an oop |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
224 if (ov->is_object() && owner_sv->obj_is_scalar_replaced()) { // The owner object was scalar replaced |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
225 assert(mv->eliminated(), "monitor should be eliminated for scalar replaced object"); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
226 // Put klass for scalar replaced object. |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
227 ScopeValue* kv = ((ObjectValue *)ov)->klass(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
228 assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object"); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
229 KlassHandle k(((ConstantOopReadValue*)kv)->value()()); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
230 result->push(new MonitorInfo(k->as_klassOop(), resolve_monitor_lock(mv->basic_lock()), |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
231 mv->eliminated(), true)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
232 } else { |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
233 result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
234 mv->eliminated(), false)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
235 } |
0 | 236 } |
237 return result; | |
238 } | |
239 | |
240 | |
241 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm) | |
242 : javaVFrame(fr, reg_map, thread) { | |
243 _scope = NULL; | |
244 // Compiled method (native stub or Java code) | |
245 // native wrappers have no scope data, it is implied | |
246 if (!nm->is_native_method()) { | |
247 _scope = nm->scope_desc_at(_fr.pc()); | |
248 } | |
249 } | |
250 | |
251 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope) | |
252 : javaVFrame(fr, reg_map, thread) { | |
253 _scope = scope; | |
254 guarantee(_scope != NULL, "scope must be present"); | |
255 } | |
256 | |
257 | |
258 bool compiledVFrame::is_top() const { | |
259 // FIX IT: Remove this when new native stubs are in place | |
260 if (scope() == NULL) return true; | |
261 return scope()->is_top(); | |
262 } | |
263 | |
264 | |
265 nmethod* compiledVFrame::code() const { | |
266 return CodeCache::find_nmethod(_fr.pc()); | |
267 } | |
268 | |
269 | |
270 methodOop compiledVFrame::method() const { | |
271 if (scope() == NULL) { | |
272 // native nmethods have no scope the method is implied | |
273 nmethod* nm = code(); | |
274 assert(nm->is_native_method(), "must be native"); | |
275 return nm->method(); | |
276 } | |
277 return scope()->method()(); | |
278 } | |
279 | |
280 | |
281 int compiledVFrame::bci() const { | |
282 int raw = raw_bci(); | |
283 return raw == SynchronizationEntryBCI ? 0 : raw; | |
284 } | |
285 | |
286 | |
287 int compiledVFrame::raw_bci() const { | |
288 if (scope() == NULL) { | |
289 // native nmethods have no scope the method/bci is implied | |
290 nmethod* nm = code(); | |
291 assert(nm->is_native_method(), "must be native"); | |
292 return 0; | |
293 } | |
294 return scope()->bci(); | |
295 } | |
296 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
297 bool compiledVFrame::should_reexecute() const { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
298 if (scope() == NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
299 // native nmethods have no scope the method/bci is implied |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
300 nmethod* nm = code(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
301 assert(nm->is_native_method(), "must be native"); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
302 return false; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
303 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
304 return scope()->should_reexecute(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
305 } |
0 | 306 |
307 vframe* compiledVFrame::sender() const { | |
308 const frame f = fr(); | |
309 if (scope() == NULL) { | |
310 // native nmethods have no scope the method/bci is implied | |
311 nmethod* nm = code(); | |
312 assert(nm->is_native_method(), "must be native"); | |
313 return vframe::sender(); | |
314 } else { | |
315 return scope()->is_top() | |
316 ? vframe::sender() | |
317 : new compiledVFrame(&f, register_map(), thread(), scope()->sender()); | |
318 } | |
319 } | |
320 | |
321 jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(methodOop method, int bci, intptr_t* id) { | |
322 _method = method; | |
323 _bci = bci; | |
324 _id = id; | |
325 // Alway will need at least one, must be on C heap | |
326 _locals = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariable*> (1, true); | |
327 } | |
328 | |
329 jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() { | |
330 for (int i = 0; i < _locals->length() ; i++ ) { | |
331 delete _locals->at(i); | |
332 } | |
333 // Free growableArray and c heap for elements | |
334 delete _locals; | |
335 } | |
336 | |
337 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) { | |
338 if (!vf->is_compiled_frame()) return false; | |
339 compiledVFrame* cvf = (compiledVFrame*)vf; | |
340 return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci(); | |
341 } | |
342 | |
343 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) { | |
344 int i; | |
345 for ( i = 0 ; i < locals()->length() ; i++ ) { | |
346 if ( locals()->at(i)->index() == idx) { | |
347 assert(locals()->at(i)->type() == type, "Wrong type"); | |
348 locals()->at(i)->set_value(val); | |
349 return; | |
350 } | |
351 } | |
352 locals()->push(new jvmtiDeferredLocalVariable(idx, type, val)); | |
353 } | |
354 | |
355 void jvmtiDeferredLocalVariableSet::oops_do(OopClosure* f) { | |
356 | |
357 f->do_oop((oop*) &_method); | |
358 for ( int i = 0; i < locals()->length(); i++ ) { | |
359 if ( locals()->at(i)->type() == T_OBJECT) { | |
360 f->do_oop(locals()->at(i)->oop_addr()); | |
361 } | |
362 } | |
363 } | |
364 | |
365 jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value) { | |
366 _index = index; | |
367 _type = type; | |
368 _value = value; | |
369 } | |
370 | |
371 | |
372 #ifndef PRODUCT | |
373 void compiledVFrame::verify() const { | |
374 Unimplemented(); | |
375 } | |
376 #endif // PRODUCT |