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