Mercurial > hg > truffle
annotate src/share/vm/runtime/vframe_hp.cpp @ 2904:1916da1d3e11
Merge.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 08 Jun 2011 17:26:49 +0200 |
parents | 06f017f7daa7 |
children | 3dbcd1013cc8 |
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 | |
1937
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
73 if (TraceDeoptimization) { |
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
74 tty->print_cr("bci=%d length=%d", this->bci(), length); |
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
75 tty->print_cr(err_msg("method name = %s", this->method()->name()->as_C_string())); |
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
76 tty->print_cr("relative pc=%d", this->fr().pc() - this->nm()->code_begin()); |
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
77 } |
4853c5cad3aa
More deoptmization tracing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1552
diff
changeset
|
78 |
0 | 79 for( int i = 0; i < length; i++ ) { |
80 result->add( create_stack_value(scv_list->at(i)) ); | |
81 } | |
82 | |
83 // Replace specified locals with any deferred writes that are present | |
84 if (deferred != NULL) { | |
85 for ( int l = 0; l < deferred->length() ; l ++) { | |
86 jvmtiDeferredLocalVariable* val = deferred->at(l); | |
87 switch (val->type()) { | |
88 case T_BOOLEAN: | |
89 result->set_int_at(val->index(), val->value().z); | |
90 break; | |
91 case T_CHAR: | |
92 result->set_int_at(val->index(), val->value().c); | |
93 break; | |
94 case T_FLOAT: | |
95 result->set_float_at(val->index(), val->value().f); | |
96 break; | |
97 case T_DOUBLE: | |
98 result->set_double_at(val->index(), val->value().d); | |
99 break; | |
100 case T_BYTE: | |
101 result->set_int_at(val->index(), val->value().b); | |
102 break; | |
103 case T_SHORT: | |
104 result->set_int_at(val->index(), val->value().s); | |
105 break; | |
106 case T_INT: | |
107 result->set_int_at(val->index(), val->value().i); | |
108 break; | |
109 case T_LONG: | |
110 result->set_long_at(val->index(), val->value().j); | |
111 break; | |
112 case T_OBJECT: | |
113 { | |
114 Handle obj((oop)val->value().l); | |
115 result->set_obj_at(val->index(), obj); | |
116 } | |
117 break; | |
118 default: | |
119 ShouldNotReachHere(); | |
120 } | |
121 } | |
122 } | |
123 | |
124 return result; | |
125 } | |
126 | |
127 | |
128 void compiledVFrame::set_locals(StackValueCollection* values) const { | |
129 | |
130 fatal("Should use update_local for each local update"); | |
131 } | |
132 | |
133 void compiledVFrame::update_local(BasicType type, int index, jvalue value) { | |
134 | |
135 #ifdef ASSERT | |
136 | |
137 assert(fr().is_deoptimized_frame(), "frame must be scheduled for deoptimization"); | |
138 #endif /* ASSERT */ | |
139 GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = thread()->deferred_locals(); | |
140 if (deferred != NULL ) { | |
141 // See if this vframe has already had locals with deferred writes | |
142 int f; | |
143 for ( f = 0 ; f < deferred->length() ; f++ ) { | |
144 if (deferred->at(f)->matches(this)) { | |
145 // Matching, vframe now see if the local already had deferred write | |
146 GrowableArray<jvmtiDeferredLocalVariable*>* locals = deferred->at(f)->locals(); | |
147 int l; | |
148 for (l = 0 ; l < locals->length() ; l++ ) { | |
149 if (locals->at(l)->index() == index) { | |
150 locals->at(l)->set_value(value); | |
151 return; | |
152 } | |
153 } | |
154 // No matching local already present. Push a new value onto the deferred collection | |
155 locals->push(new jvmtiDeferredLocalVariable(index, type, value)); | |
156 return; | |
157 } | |
158 } | |
159 // No matching vframe must push a new vframe | |
160 } else { | |
161 // No deferred updates pending for this thread. | |
162 // allocate in C heap | |
163 deferred = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true); | |
164 thread()->set_deferred_locals(deferred); | |
165 } | |
166 deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id())); | |
167 assert(deferred->top()->id() == fr().id(), "Huh? Must match"); | |
168 deferred->top()->set_local_at(index, type, value); | |
169 } | |
170 | |
171 StackValueCollection* compiledVFrame::expressions() const { | |
172 // Natives has no scope | |
173 if (scope() == NULL) return new StackValueCollection(0); | |
174 GrowableArray<ScopeValue*>* scv_list = scope()->expressions(); | |
175 if (scv_list == NULL) return new StackValueCollection(0); | |
176 | |
177 // scv_list is the list of ScopeValues describing the JVM stack state. | |
178 // There is one scv_list entry for every JVM stack state in use. | |
179 int length = scv_list->length(); | |
180 StackValueCollection* result = new StackValueCollection(length); | |
181 for( int i = 0; i < length; i++ ) | |
182 result->add( create_stack_value(scv_list->at(i)) ); | |
183 | |
184 return result; | |
185 } | |
186 | |
187 | |
188 // The implementation of the following two methods was factorized into the | |
189 // class StackValue because it is also used from within deoptimization.cpp for | |
190 // rematerialization and relocking of non-escaping objects. | |
191 | |
192 StackValue *compiledVFrame::create_stack_value(ScopeValue *sv) const { | |
193 return StackValue::create_stack_value(&_fr, register_map(), sv); | |
194 } | |
195 | |
196 BasicLock* compiledVFrame::resolve_monitor_lock(Location location) const { | |
197 return StackValue::resolve_monitor_lock(&_fr, location); | |
198 } | |
199 | |
200 | |
201 GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const { | |
202 // Natives has no scope | |
203 if (scope() == NULL) { | |
204 nmethod* nm = code(); | |
205 methodOop method = nm->method(); | |
206 assert(method->is_native(), ""); | |
207 if (!method->is_synchronized()) { | |
208 return new GrowableArray<MonitorInfo*>(0); | |
209 } | |
210 // This monitor is really only needed for UseBiasedLocking, but | |
211 // return it in all cases for now as it might be useful for stack | |
212 // traces and tools as well | |
213 GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1); | |
214 // Casting away const | |
215 frame& fr = (frame&) _fr; | |
2019 | 216 MonitorInfo* info = new MonitorInfo( |
217 fr.get_native_receiver(), fr.get_native_monitor(), false, false); | |
0 | 218 monitors->push(info); |
219 return monitors; | |
220 } | |
221 GrowableArray<MonitorValue*>* monitors = scope()->monitors(); | |
222 if (monitors == NULL) { | |
223 return new GrowableArray<MonitorInfo*>(0); | |
224 } | |
225 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(monitors->length()); | |
226 for (int index = 0; index < monitors->length(); index++) { | |
227 MonitorValue* mv = monitors->at(index); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
228 ScopeValue* ov = mv->owner(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
229 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
|
230 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
|
231 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
|
232 // Put klass for scalar replaced object. |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
233 ScopeValue* kv = ((ObjectValue *)ov)->klass(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
234 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
|
235 KlassHandle k(((ConstantOopReadValue*)kv)->value()()); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
236 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
|
237 mv->eliminated(), true)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
238 } else { |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
239 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
|
240 mv->eliminated(), false)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
196
diff
changeset
|
241 } |
0 | 242 } |
243 return result; | |
244 } | |
245 | |
246 | |
247 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm) | |
248 : javaVFrame(fr, reg_map, thread) { | |
249 _scope = NULL; | |
250 // Compiled method (native stub or Java code) | |
251 // native wrappers have no scope data, it is implied | |
252 if (!nm->is_native_method()) { | |
253 _scope = nm->scope_desc_at(_fr.pc()); | |
254 } | |
255 } | |
256 | |
257 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope) | |
258 : javaVFrame(fr, reg_map, thread) { | |
259 _scope = scope; | |
260 guarantee(_scope != NULL, "scope must be present"); | |
261 } | |
262 | |
263 | |
264 bool compiledVFrame::is_top() const { | |
265 // FIX IT: Remove this when new native stubs are in place | |
266 if (scope() == NULL) return true; | |
267 return scope()->is_top(); | |
268 } | |
269 | |
270 | |
271 nmethod* compiledVFrame::code() const { | |
272 return CodeCache::find_nmethod(_fr.pc()); | |
273 } | |
274 | |
275 | |
276 methodOop compiledVFrame::method() const { | |
277 if (scope() == NULL) { | |
278 // native nmethods have no scope the method is implied | |
279 nmethod* nm = code(); | |
280 assert(nm->is_native_method(), "must be native"); | |
281 return nm->method(); | |
282 } | |
283 return scope()->method()(); | |
284 } | |
285 | |
286 | |
287 int compiledVFrame::bci() const { | |
288 int raw = raw_bci(); | |
289 return raw == SynchronizationEntryBCI ? 0 : raw; | |
290 } | |
291 | |
292 | |
293 int compiledVFrame::raw_bci() const { | |
294 if (scope() == NULL) { | |
295 // native nmethods have no scope the method/bci is implied | |
296 nmethod* nm = code(); | |
297 assert(nm->is_native_method(), "must be native"); | |
298 return 0; | |
299 } | |
300 return scope()->bci(); | |
301 } | |
302 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
303 bool compiledVFrame::should_reexecute() const { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
304 if (scope() == NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
305 // 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
|
306 nmethod* nm = code(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
307 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
|
308 return false; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
309 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
310 return scope()->should_reexecute(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
311 } |
0 | 312 |
313 vframe* compiledVFrame::sender() const { | |
314 const frame f = fr(); | |
315 if (scope() == NULL) { | |
316 // native nmethods have no scope the method/bci is implied | |
317 nmethod* nm = code(); | |
318 assert(nm->is_native_method(), "must be native"); | |
319 return vframe::sender(); | |
320 } else { | |
321 return scope()->is_top() | |
322 ? vframe::sender() | |
323 : new compiledVFrame(&f, register_map(), thread(), scope()->sender()); | |
324 } | |
325 } | |
326 | |
327 jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(methodOop method, int bci, intptr_t* id) { | |
328 _method = method; | |
329 _bci = bci; | |
330 _id = id; | |
331 // Alway will need at least one, must be on C heap | |
332 _locals = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariable*> (1, true); | |
333 } | |
334 | |
335 jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() { | |
336 for (int i = 0; i < _locals->length() ; i++ ) { | |
337 delete _locals->at(i); | |
338 } | |
339 // Free growableArray and c heap for elements | |
340 delete _locals; | |
341 } | |
342 | |
343 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) { | |
344 if (!vf->is_compiled_frame()) return false; | |
345 compiledVFrame* cvf = (compiledVFrame*)vf; | |
346 return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci(); | |
347 } | |
348 | |
349 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) { | |
350 int i; | |
351 for ( i = 0 ; i < locals()->length() ; i++ ) { | |
352 if ( locals()->at(i)->index() == idx) { | |
353 assert(locals()->at(i)->type() == type, "Wrong type"); | |
354 locals()->at(i)->set_value(val); | |
355 return; | |
356 } | |
357 } | |
358 locals()->push(new jvmtiDeferredLocalVariable(idx, type, val)); | |
359 } | |
360 | |
361 void jvmtiDeferredLocalVariableSet::oops_do(OopClosure* f) { | |
362 | |
363 f->do_oop((oop*) &_method); | |
364 for ( int i = 0; i < locals()->length(); i++ ) { | |
365 if ( locals()->at(i)->type() == T_OBJECT) { | |
366 f->do_oop(locals()->at(i)->oop_addr()); | |
367 } | |
368 } | |
369 } | |
370 | |
371 jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value) { | |
372 _index = index; | |
373 _type = type; | |
374 _value = value; | |
375 } | |
376 | |
377 | |
378 #ifndef PRODUCT | |
379 void compiledVFrame::verify() const { | |
380 Unimplemented(); | |
381 } | |
382 #endif // PRODUCT |