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