1 /* 2 * Copyright 1997-2009 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/_scopeDesc.cpp.incl" 27 28 29 ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) { 30 _code = code; 31 _decode_offset = decode_offset; 32 _objects = decode_object_values(obj_decode_offset); 33 _reexecute = reexecute; 34 decode_body(); 35 } 36 37 ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) { 38 _code = code; 39 _decode_offset = decode_offset; 40 _objects = decode_object_values(DebugInformationRecorder::serialized_null); 41 _reexecute = reexecute; 42 decode_body(); 43 } 44 45 46 ScopeDesc::ScopeDesc(const ScopeDesc* parent) { 47 _code = parent->_code; 48 _decode_offset = parent->_sender_decode_offset; 49 _objects = parent->_objects; 50 _reexecute = false; //reexecute only applies to the first scope 51 decode_body(); 52 } 53 54 55 void ScopeDesc::decode_body() { 56 if (decode_offset() == DebugInformationRecorder::serialized_null) { 57 // This is a sentinel record, which is only relevant to 58 // approximate queries. Decode a reasonable frame. 59 _sender_decode_offset = DebugInformationRecorder::serialized_null; 60 _method = methodHandle(_code->method()); 61 _bci = InvocationEntryBci; 62 _locals_decode_offset = DebugInformationRecorder::serialized_null; 63 _expressions_decode_offset = DebugInformationRecorder::serialized_null; 64 _monitors_decode_offset = DebugInformationRecorder::serialized_null; 65 } else { 66 // decode header 67 DebugInfoReadStream* stream = stream_at(decode_offset()); 68 69 _sender_decode_offset = stream->read_int(); 70 _method = methodHandle((methodOop) stream->read_oop()); 71 _bci = stream->read_bci(); 72 73 // decode offsets for body and sender 74 _locals_decode_offset = stream->read_int(); 75 _expressions_decode_offset = stream->read_int(); 76 _monitors_decode_offset = stream->read_int(); 77 } 78 } 79 80 81 GrowableArray<ScopeValue*>* ScopeDesc::decode_scope_values(int decode_offset) { 82 if (decode_offset == DebugInformationRecorder::serialized_null) return NULL; 83 DebugInfoReadStream* stream = stream_at(decode_offset); 84 int length = stream->read_int(); 85 GrowableArray<ScopeValue*>* result = new GrowableArray<ScopeValue*> (length); 86 for (int index = 0; index < length; index++) { 87 result->push(ScopeValue::read_from(stream)); 88 } 89 return result; 90 } 91 92 GrowableArray<ScopeValue*>* ScopeDesc::decode_object_values(int decode_offset) { 93 if (decode_offset == DebugInformationRecorder::serialized_null) return NULL; 94 GrowableArray<ScopeValue*>* result = new GrowableArray<ScopeValue*>(); 95 DebugInfoReadStream* stream = new DebugInfoReadStream(_code, decode_offset, result); 96 int length = stream->read_int(); 97 for (int index = 0; index < length; index++) { 98 // Objects values are pushed to 'result' array during read so that 99 // object's fields could reference it (OBJECT_ID_CODE). 100 (void)ScopeValue::read_from(stream); 101 } 102 assert(result->length() == length, "inconsistent debug information"); 103 return result; 104 } 105 106 107 GrowableArray<MonitorValue*>* ScopeDesc::decode_monitor_values(int decode_offset) { 108 if (decode_offset == DebugInformationRecorder::serialized_null) return NULL; 109 DebugInfoReadStream* stream = stream_at(decode_offset); 110 int length = stream->read_int(); 111 GrowableArray<MonitorValue*>* result = new GrowableArray<MonitorValue*> (length); 112 for (int index = 0; index < length; index++) { 113 result->push(new MonitorValue(stream)); 114 } 115 return result; 116 } 117 118 DebugInfoReadStream* ScopeDesc::stream_at(int decode_offset) const { 119 return new DebugInfoReadStream(_code, decode_offset, _objects); 120 } 121 122 GrowableArray<ScopeValue*>* ScopeDesc::locals() { 123 return decode_scope_values(_locals_decode_offset); 124 } 125 126 GrowableArray<ScopeValue*>* ScopeDesc::expressions() { 127 return decode_scope_values(_expressions_decode_offset); 128 } 129 130 GrowableArray<MonitorValue*>* ScopeDesc::monitors() { 131 return decode_monitor_values(_monitors_decode_offset); 132 } 133 134 GrowableArray<ScopeValue*>* ScopeDesc::objects() { 135 return _objects; 136 } 137 138 bool ScopeDesc::is_top() const { 139 return _sender_decode_offset == DebugInformationRecorder::serialized_null; 140 } 141 142 ScopeDesc* ScopeDesc::sender() const { 143 if (is_top()) return NULL; 144 return new ScopeDesc(this); 145 } 146 147 148 #ifndef PRODUCT 149 150 void ScopeDesc::print_value_on(outputStream* st) const { 151 tty->print(" "); 152 method()()->print_short_name(st); 153 int lineno = method()->line_number_from_bci(bci()); 154 if (lineno != -1) { 155 st->print_cr("@%d (line %d)", bci(), lineno); 156 } else { 157 st->print_cr("@%d", bci()); 158 } 159 } 160 161 void ScopeDesc::print_on(outputStream* st) const { 162 print_on(st, NULL); 163 } 164 165 void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const { 166 // header 167 if (pd != NULL) { 168 tty->print_cr("ScopeDesc(pc=" PTR_FORMAT " offset=%x):", pd->real_pc(_code), pd->pc_offset()); 169 } 170 171 print_value_on(st); 172 // decode offsets 173 if (WizardMode) { 174 st->print("ScopeDesc[%d]@" PTR_FORMAT " ", _decode_offset, _code->instructions_begin()); 175 st->print_cr(" offset: %d", _decode_offset); 176 st->print_cr(" bci: %d", bci()); 177 st->print_cr(" reexecute: %s", should_reexecute() ? "true" : "false"); 178 st->print_cr(" locals: %d", _locals_decode_offset); 179 st->print_cr(" stack: %d", _expressions_decode_offset); 180 st->print_cr(" monitor: %d", _monitors_decode_offset); 181 st->print_cr(" sender: %d", _sender_decode_offset); 182 } 183 // locals 184 { GrowableArray<ScopeValue*>* l = ((ScopeDesc*) this)->locals(); 185 if (l != NULL) { 186 tty->print_cr(" Locals"); 187 for (int index = 0; index < l->length(); index++) { 188 st->print(" - l%d: ", index); 189 l->at(index)->print_on(st); 190 st->cr(); 191 } 192 } 193 } 194 // expressions 195 { GrowableArray<ScopeValue*>* l = ((ScopeDesc*) this)->expressions(); 196 if (l != NULL) { 197 st->print_cr(" Expression stack"); 198 for (int index = 0; index < l->length(); index++) { 199 st->print(" - @%d: ", index); 200 l->at(index)->print_on(st); 201 st->cr(); 202 } 203 } 204 } 205 // monitors 206 { GrowableArray<MonitorValue*>* l = ((ScopeDesc*) this)->monitors(); 207 if (l != NULL) { 208 st->print_cr(" Monitor stack"); 209 for (int index = 0; index < l->length(); index++) { 210 st->print(" - @%d: ", index); 211 l->at(index)->print_on(st); 212 st->cr(); 213 } 214 } 215 } 216 217 #ifdef COMPILER2 218 if (DoEscapeAnalysis && is_top() && _objects != NULL) { 219 tty->print_cr("Objects"); 220 for (int i = 0; i < _objects->length(); i++) { 221 ObjectValue* sv = (ObjectValue*) _objects->at(i); 222 tty->print(" - %d: ", sv->id()); 223 sv->print_fields_on(tty); 224 tty->cr(); 225 } 226 } 227 #endif // COMPILER2 228 } 229 230 #endif 231 232 void ScopeDesc::verify() { 233 ResourceMark rm; 234 guarantee(method()->is_method(), "type check"); 235 236 // check if we have any illegal elements on the expression stack 237 { GrowableArray<ScopeValue*>* l = expressions(); 238 if (l != NULL) { 239 for (int index = 0; index < l->length(); index++) { 240 //guarantee(!l->at(index)->is_illegal(), "expression element cannot be illegal"); 241 } 242 } 243 } 244 }