Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/vframe_hp.cpp @ 103:38a50dd839cf
6619271: The -Xprintflags causes the VM to segv
Summary: add null checks
Reviewed-by: jrose, kvn
author | never |
---|---|
date | Thu, 03 Apr 2008 10:20:44 -0700 |
parents | d3cd40645d0d |
children | d1605aabd0a1 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. | |
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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_vframe_hp.cpp.incl" | |
27 | |
28 | |
29 // ------------- compiledVFrame -------------- | |
30 | |
31 StackValueCollection* compiledVFrame::locals() const { | |
32 // Natives has no scope | |
33 if (scope() == NULL) return new StackValueCollection(0); | |
34 GrowableArray<ScopeValue*>* scv_list = scope()->locals(); | |
35 if (scv_list == NULL) return new StackValueCollection(0); | |
36 | |
37 // scv_list is the list of ScopeValues describing the JVM stack state. | |
38 // There is one scv_list entry for every JVM stack state in use. | |
39 int length = scv_list->length(); | |
40 StackValueCollection* result = new StackValueCollection(length); | |
41 // In rare instances set_locals may have occurred in which case | |
42 // there are local values that are not described by the ScopeValue anymore | |
43 GrowableArray<jvmtiDeferredLocalVariable*>* deferred = NULL; | |
44 GrowableArray<jvmtiDeferredLocalVariableSet*>* list = thread()->deferred_locals(); | |
45 if (list != NULL ) { | |
46 // In real life this never happens or is typically a single element search | |
47 for (int i = 0; i < list->length(); i++) { | |
48 if (list->at(i)->matches((vframe*)this)) { | |
49 deferred = list->at(i)->locals(); | |
50 break; | |
51 } | |
52 } | |
53 } | |
54 | |
55 for( int i = 0; i < length; i++ ) { | |
56 result->add( create_stack_value(scv_list->at(i)) ); | |
57 } | |
58 | |
59 // Replace specified locals with any deferred writes that are present | |
60 if (deferred != NULL) { | |
61 for ( int l = 0; l < deferred->length() ; l ++) { | |
62 jvmtiDeferredLocalVariable* val = deferred->at(l); | |
63 switch (val->type()) { | |
64 case T_BOOLEAN: | |
65 result->set_int_at(val->index(), val->value().z); | |
66 break; | |
67 case T_CHAR: | |
68 result->set_int_at(val->index(), val->value().c); | |
69 break; | |
70 case T_FLOAT: | |
71 result->set_float_at(val->index(), val->value().f); | |
72 break; | |
73 case T_DOUBLE: | |
74 result->set_double_at(val->index(), val->value().d); | |
75 break; | |
76 case T_BYTE: | |
77 result->set_int_at(val->index(), val->value().b); | |
78 break; | |
79 case T_SHORT: | |
80 result->set_int_at(val->index(), val->value().s); | |
81 break; | |
82 case T_INT: | |
83 result->set_int_at(val->index(), val->value().i); | |
84 break; | |
85 case T_LONG: | |
86 result->set_long_at(val->index(), val->value().j); | |
87 break; | |
88 case T_OBJECT: | |
89 { | |
90 Handle obj((oop)val->value().l); | |
91 result->set_obj_at(val->index(), obj); | |
92 } | |
93 break; | |
94 default: | |
95 ShouldNotReachHere(); | |
96 } | |
97 } | |
98 } | |
99 | |
100 return result; | |
101 } | |
102 | |
103 | |
104 void compiledVFrame::set_locals(StackValueCollection* values) const { | |
105 | |
106 fatal("Should use update_local for each local update"); | |
107 } | |
108 | |
109 void compiledVFrame::update_local(BasicType type, int index, jvalue value) { | |
110 | |
111 #ifdef ASSERT | |
112 | |
113 assert(fr().is_deoptimized_frame(), "frame must be scheduled for deoptimization"); | |
114 #endif /* ASSERT */ | |
115 GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = thread()->deferred_locals(); | |
116 if (deferred != NULL ) { | |
117 // See if this vframe has already had locals with deferred writes | |
118 int f; | |
119 for ( f = 0 ; f < deferred->length() ; f++ ) { | |
120 if (deferred->at(f)->matches(this)) { | |
121 // Matching, vframe now see if the local already had deferred write | |
122 GrowableArray<jvmtiDeferredLocalVariable*>* locals = deferred->at(f)->locals(); | |
123 int l; | |
124 for (l = 0 ; l < locals->length() ; l++ ) { | |
125 if (locals->at(l)->index() == index) { | |
126 locals->at(l)->set_value(value); | |
127 return; | |
128 } | |
129 } | |
130 // No matching local already present. Push a new value onto the deferred collection | |
131 locals->push(new jvmtiDeferredLocalVariable(index, type, value)); | |
132 return; | |
133 } | |
134 } | |
135 // No matching vframe must push a new vframe | |
136 } else { | |
137 // No deferred updates pending for this thread. | |
138 // allocate in C heap | |
139 deferred = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true); | |
140 thread()->set_deferred_locals(deferred); | |
141 } | |
142 deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id())); | |
143 assert(deferred->top()->id() == fr().id(), "Huh? Must match"); | |
144 deferred->top()->set_local_at(index, type, value); | |
145 } | |
146 | |
147 StackValueCollection* compiledVFrame::expressions() const { | |
148 // Natives has no scope | |
149 if (scope() == NULL) return new StackValueCollection(0); | |
150 GrowableArray<ScopeValue*>* scv_list = scope()->expressions(); | |
151 if (scv_list == NULL) return new StackValueCollection(0); | |
152 | |
153 // scv_list is the list of ScopeValues describing the JVM stack state. | |
154 // There is one scv_list entry for every JVM stack state in use. | |
155 int length = scv_list->length(); | |
156 StackValueCollection* result = new StackValueCollection(length); | |
157 for( int i = 0; i < length; i++ ) | |
158 result->add( create_stack_value(scv_list->at(i)) ); | |
159 | |
160 return result; | |
161 } | |
162 | |
163 | |
164 // The implementation of the following two methods was factorized into the | |
165 // class StackValue because it is also used from within deoptimization.cpp for | |
166 // rematerialization and relocking of non-escaping objects. | |
167 | |
168 StackValue *compiledVFrame::create_stack_value(ScopeValue *sv) const { | |
169 return StackValue::create_stack_value(&_fr, register_map(), sv); | |
170 } | |
171 | |
172 BasicLock* compiledVFrame::resolve_monitor_lock(Location location) const { | |
173 return StackValue::resolve_monitor_lock(&_fr, location); | |
174 } | |
175 | |
176 | |
177 GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const { | |
178 // Natives has no scope | |
179 if (scope() == NULL) { | |
180 nmethod* nm = code(); | |
181 methodOop method = nm->method(); | |
182 assert(method->is_native(), ""); | |
183 if (!method->is_synchronized()) { | |
184 return new GrowableArray<MonitorInfo*>(0); | |
185 } | |
186 // This monitor is really only needed for UseBiasedLocking, but | |
187 // return it in all cases for now as it might be useful for stack | |
188 // traces and tools as well | |
189 GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1); | |
190 // Casting away const | |
191 frame& fr = (frame&) _fr; | |
192 MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm), | |
83
d3cd40645d0d
6681646: Relocking of a scalar replaced object during deoptimization is broken
kvn
parents:
0
diff
changeset
|
193 fr.compiled_synchronized_native_monitor(nm), false); |
0 | 194 monitors->push(info); |
195 return monitors; | |
196 } | |
197 GrowableArray<MonitorValue*>* monitors = scope()->monitors(); | |
198 if (monitors == NULL) { | |
199 return new GrowableArray<MonitorInfo*>(0); | |
200 } | |
201 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(monitors->length()); | |
202 for (int index = 0; index < monitors->length(); index++) { | |
203 MonitorValue* mv = monitors->at(index); | |
204 StackValue *owner_sv = create_stack_value(mv->owner()); // it is an oop | |
83
d3cd40645d0d
6681646: Relocking of a scalar replaced object during deoptimization is broken
kvn
parents:
0
diff
changeset
|
205 result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated())); |
0 | 206 } |
207 return result; | |
208 } | |
209 | |
210 | |
211 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm) | |
212 : javaVFrame(fr, reg_map, thread) { | |
213 _scope = NULL; | |
214 // Compiled method (native stub or Java code) | |
215 // native wrappers have no scope data, it is implied | |
216 if (!nm->is_native_method()) { | |
217 _scope = nm->scope_desc_at(_fr.pc()); | |
218 } | |
219 } | |
220 | |
221 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope) | |
222 : javaVFrame(fr, reg_map, thread) { | |
223 _scope = scope; | |
224 guarantee(_scope != NULL, "scope must be present"); | |
225 } | |
226 | |
227 | |
228 bool compiledVFrame::is_top() const { | |
229 // FIX IT: Remove this when new native stubs are in place | |
230 if (scope() == NULL) return true; | |
231 return scope()->is_top(); | |
232 } | |
233 | |
234 | |
235 nmethod* compiledVFrame::code() const { | |
236 return CodeCache::find_nmethod(_fr.pc()); | |
237 } | |
238 | |
239 | |
240 methodOop compiledVFrame::method() const { | |
241 if (scope() == NULL) { | |
242 // native nmethods have no scope the method is implied | |
243 nmethod* nm = code(); | |
244 assert(nm->is_native_method(), "must be native"); | |
245 return nm->method(); | |
246 } | |
247 return scope()->method()(); | |
248 } | |
249 | |
250 | |
251 int compiledVFrame::bci() const { | |
252 int raw = raw_bci(); | |
253 return raw == SynchronizationEntryBCI ? 0 : raw; | |
254 } | |
255 | |
256 | |
257 int compiledVFrame::raw_bci() const { | |
258 if (scope() == NULL) { | |
259 // native nmethods have no scope the method/bci is implied | |
260 nmethod* nm = code(); | |
261 assert(nm->is_native_method(), "must be native"); | |
262 return 0; | |
263 } | |
264 return scope()->bci(); | |
265 } | |
266 | |
267 | |
268 vframe* compiledVFrame::sender() const { | |
269 const frame f = fr(); | |
270 if (scope() == NULL) { | |
271 // native nmethods have no scope the method/bci is implied | |
272 nmethod* nm = code(); | |
273 assert(nm->is_native_method(), "must be native"); | |
274 return vframe::sender(); | |
275 } else { | |
276 return scope()->is_top() | |
277 ? vframe::sender() | |
278 : new compiledVFrame(&f, register_map(), thread(), scope()->sender()); | |
279 } | |
280 } | |
281 | |
282 jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(methodOop method, int bci, intptr_t* id) { | |
283 _method = method; | |
284 _bci = bci; | |
285 _id = id; | |
286 // Alway will need at least one, must be on C heap | |
287 _locals = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariable*> (1, true); | |
288 } | |
289 | |
290 jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() { | |
291 for (int i = 0; i < _locals->length() ; i++ ) { | |
292 delete _locals->at(i); | |
293 } | |
294 // Free growableArray and c heap for elements | |
295 delete _locals; | |
296 } | |
297 | |
298 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) { | |
299 if (!vf->is_compiled_frame()) return false; | |
300 compiledVFrame* cvf = (compiledVFrame*)vf; | |
301 return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci(); | |
302 } | |
303 | |
304 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) { | |
305 int i; | |
306 for ( i = 0 ; i < locals()->length() ; i++ ) { | |
307 if ( locals()->at(i)->index() == idx) { | |
308 assert(locals()->at(i)->type() == type, "Wrong type"); | |
309 locals()->at(i)->set_value(val); | |
310 return; | |
311 } | |
312 } | |
313 locals()->push(new jvmtiDeferredLocalVariable(idx, type, val)); | |
314 } | |
315 | |
316 void jvmtiDeferredLocalVariableSet::oops_do(OopClosure* f) { | |
317 | |
318 f->do_oop((oop*) &_method); | |
319 for ( int i = 0; i < locals()->length(); i++ ) { | |
320 if ( locals()->at(i)->type() == T_OBJECT) { | |
321 f->do_oop(locals()->at(i)->oop_addr()); | |
322 } | |
323 } | |
324 } | |
325 | |
326 jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value) { | |
327 _index = index; | |
328 _type = type; | |
329 _value = value; | |
330 } | |
331 | |
332 | |
333 #ifndef PRODUCT | |
334 void compiledVFrame::verify() const { | |
335 Unimplemented(); | |
336 } | |
337 #endif // PRODUCT |