1 /* 2 * Copyright 1997-2008 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), 193 fr.compiled_synchronized_native_monitor(nm), false, false); 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 ScopeValue* ov = mv->owner(); 205 StackValue *owner_sv = create_stack_value(ov); // it is an oop 206 if (ov->is_object() && owner_sv->obj_is_scalar_replaced()) { // The owner object was scalar replaced 207 assert(mv->eliminated(), "monitor should be eliminated for scalar replaced object"); 208 // Put klass for scalar replaced object. 209 ScopeValue* kv = ((ObjectValue *)ov)->klass(); 210 assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object"); 211 KlassHandle k(((ConstantOopReadValue*)kv)->value()()); 212 result->push(new MonitorInfo(k->as_klassOop(), resolve_monitor_lock(mv->basic_lock()), 213 mv->eliminated(), true)); 214 } else { 215 result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), 216 mv->eliminated(), false)); 217 } 218 } 219 return result; 220 } 221 222 223 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm) 224 : javaVFrame(fr, reg_map, thread) { 225 _scope = NULL; 226 // Compiled method (native stub or Java code) 227 // native wrappers have no scope data, it is implied 228 if (!nm->is_native_method()) { 229 _scope = nm->scope_desc_at(_fr.pc()); 230 } 231 } 232 233 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope) 234 : javaVFrame(fr, reg_map, thread) { 235 _scope = scope; 236 guarantee(_scope != NULL, "scope must be present"); 237 } 238 239 240 bool compiledVFrame::is_top() const { 241 // FIX IT: Remove this when new native stubs are in place 242 if (scope() == NULL) return true; 243 return scope()->is_top(); 244 } 245 246 247 nmethod* compiledVFrame::code() const { 248 return CodeCache::find_nmethod(_fr.pc()); 249 } 250 251 252 methodOop compiledVFrame::method() const { 253 if (scope() == NULL) { 254 // native nmethods have no scope the method is implied 255 nmethod* nm = code(); 256 assert(nm->is_native_method(), "must be native"); 257 return nm->method(); 258 } 259 return scope()->method()(); 260 } 261 262 263 int compiledVFrame::bci() const { 264 int raw = raw_bci(); 265 return raw == SynchronizationEntryBCI ? 0 : raw; 266 } 267 268 269 int compiledVFrame::raw_bci() const { 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 0; 275 } 276 return scope()->bci(); 277 } 278 279 280 vframe* compiledVFrame::sender() const { 281 const frame f = fr(); 282 if (scope() == NULL) { 283 // native nmethods have no scope the method/bci is implied 284 nmethod* nm = code(); 285 assert(nm->is_native_method(), "must be native"); 286 return vframe::sender(); 287 } else { 288 return scope()->is_top() 289 ? vframe::sender() 290 : new compiledVFrame(&f, register_map(), thread(), scope()->sender()); 291 } 292 } 293 294 jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(methodOop method, int bci, intptr_t* id) { 295 _method = method; 296 _bci = bci; 297 _id = id; 298 // Alway will need at least one, must be on C heap 299 _locals = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariable*> (1, true); 300 } 301 302 jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() { 303 for (int i = 0; i < _locals->length() ; i++ ) { 304 delete _locals->at(i); 305 } 306 // Free growableArray and c heap for elements 307 delete _locals; 308 } 309 310 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) { 311 if (!vf->is_compiled_frame()) return false; 312 compiledVFrame* cvf = (compiledVFrame*)vf; 313 return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci(); 314 } 315 316 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) { 317 int i; 318 for ( i = 0 ; i < locals()->length() ; i++ ) { 319 if ( locals()->at(i)->index() == idx) { 320 assert(locals()->at(i)->type() == type, "Wrong type"); 321 locals()->at(i)->set_value(val); 322 return; 323 } 324 } 325 locals()->push(new jvmtiDeferredLocalVariable(idx, type, val)); 326 } 327 328 void jvmtiDeferredLocalVariableSet::oops_do(OopClosure* f) { 329 330 f->do_oop((oop*) &_method); 331 for ( int i = 0; i < locals()->length(); i++ ) { 332 if ( locals()->at(i)->type() == T_OBJECT) { 333 f->do_oop(locals()->at(i)->oop_addr()); 334 } 335 } 336 } 337 338 jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value) { 339 _index = index; 340 _type = type; 341 _value = value; 342 } 343 344 345 #ifndef PRODUCT 346 void compiledVFrame::verify() const { 347 Unimplemented(); 348 } 349 #endif // PRODUCT