1/*
2 * Copyright (c) 1997, 2018, 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/debugInfo.hpp"
27#include "code/debugInfoRec.hpp"
28#include "code/nmethod.hpp"
29#include "memory/universe.hpp"
30#include "oops/oop.inline.hpp"
31#include "runtime/handles.inline.hpp"
32#include "runtime/interfaceSupport.inline.hpp"
33#include "runtime/jniHandles.inline.hpp"
34#include "runtime/thread.hpp"
35
36// Constructors
37
38DebugInfoWriteStream::DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size)
39: CompressedWriteStream(initial_size) {
40 _recorder = recorder;
41}
42
43// Serializing oops
44
45void DebugInfoWriteStream::write_handle(jobject h) {
46 write_int(recorder()->oop_recorder()->find_index(h));
47}
48
49void DebugInfoWriteStream::write_metadata(Metadata* h) {
50 write_int(recorder()->oop_recorder()->find_index(h));
51}
52
53oop DebugInfoReadStream::read_oop() {
54 oop o = code()->oop_at(read_int());
55 assert(oopDesc::is_oop_or_null(o), "oop only");
56 return o;
57}
58
59ScopeValue* DebugInfoReadStream::read_object_value(bool is_auto_box) {
60 int id = read_int();
61#ifdef ASSERT
62 assert(_obj_pool != NULL, "object pool does not exist");
63 for (int i = _obj_pool->length() - 1; i >= 0; i--) {
64 assert(_obj_pool->at(i)->as_ObjectValue()->id() != id, "should not be read twice");
65 }
66#endif
67 ObjectValue* result = is_auto_box ? new AutoBoxObjectValue(id) : new ObjectValue(id);
68 // Cache the object since an object field could reference it.
69 _obj_pool->push(result);
70 result->read_object(this);
71 return result;
72}
73
74ScopeValue* DebugInfoReadStream::get_cached_object() {
75 int id = read_int();
76 assert(_obj_pool != NULL, "object pool does not exist");
77 for (int i = _obj_pool->length() - 1; i >= 0; i--) {
78 ObjectValue* ov = _obj_pool->at(i)->as_ObjectValue();
79 if (ov->id() == id) {
80 return ov;
81 }
82 }
83 ShouldNotReachHere();
84 return NULL;
85}
86
87// Serializing scope values
88
89enum { LOCATION_CODE = 0, CONSTANT_INT_CODE = 1, CONSTANT_OOP_CODE = 2,
90 CONSTANT_LONG_CODE = 3, CONSTANT_DOUBLE_CODE = 4,
91 OBJECT_CODE = 5, OBJECT_ID_CODE = 6,
92 AUTO_BOX_OBJECT_CODE = 7 };
93
94ScopeValue* ScopeValue::read_from(DebugInfoReadStream* stream) {
95 ScopeValue* result = NULL;
96 switch(stream->read_int()) {
97 case LOCATION_CODE: result = new LocationValue(stream); break;
98 case CONSTANT_INT_CODE: result = new ConstantIntValue(stream); break;
99 case CONSTANT_OOP_CODE: result = new ConstantOopReadValue(stream); break;
100 case CONSTANT_LONG_CODE: result = new ConstantLongValue(stream); break;
101 case CONSTANT_DOUBLE_CODE: result = new ConstantDoubleValue(stream); break;
102 case OBJECT_CODE: result = stream->read_object_value(false /*is_auto_box*/); break;
103 case AUTO_BOX_OBJECT_CODE: result = stream->read_object_value(true /*is_auto_box*/); break;
104 case OBJECT_ID_CODE: result = stream->get_cached_object(); break;
105 default: ShouldNotReachHere();
106 }
107 return result;
108}
109
110// LocationValue
111
112LocationValue::LocationValue(DebugInfoReadStream* stream) {
113 _location = Location(stream);
114}
115
116void LocationValue::write_on(DebugInfoWriteStream* stream) {
117 stream->write_int(LOCATION_CODE);
118 location().write_on(stream);
119}
120
121void LocationValue::print_on(outputStream* st) const {
122 location().print_on(st);
123}
124
125// ObjectValue
126
127void ObjectValue::set_value(oop value) {
128 _value = Handle(Thread::current(), value);
129}
130
131void ObjectValue::read_object(DebugInfoReadStream* stream) {
132 _klass = read_from(stream);
133 assert(_klass->is_constant_oop(), "should be constant java mirror oop");
134 int length = stream->read_int();
135 for (int i = 0; i < length; i++) {
136 ScopeValue* val = read_from(stream);
137 _field_values.append(val);
138 }
139}
140
141void ObjectValue::write_on(DebugInfoWriteStream* stream) {
142 if (_visited) {
143 stream->write_int(OBJECT_ID_CODE);
144 stream->write_int(_id);
145 } else {
146 _visited = true;
147 stream->write_int(is_auto_box() ? AUTO_BOX_OBJECT_CODE : OBJECT_CODE);
148 stream->write_int(_id);
149 _klass->write_on(stream);
150 int length = _field_values.length();
151 stream->write_int(length);
152 for (int i = 0; i < length; i++) {
153 _field_values.at(i)->write_on(stream);
154 }
155 }
156}
157
158void ObjectValue::print_on(outputStream* st) const {
159 st->print("%s[%d]", is_auto_box() ? "box_obj" : "obj", _id);
160}
161
162void ObjectValue::print_fields_on(outputStream* st) const {
163#ifndef PRODUCT
164 if (_field_values.length() > 0) {
165 _field_values.at(0)->print_on(st);
166 }
167 for (int i = 1; i < _field_values.length(); i++) {
168 st->print(", ");
169 _field_values.at(i)->print_on(st);
170 }
171#endif
172}
173
174// ConstantIntValue
175
176ConstantIntValue::ConstantIntValue(DebugInfoReadStream* stream) {
177 _value = stream->read_signed_int();
178}
179
180void ConstantIntValue::write_on(DebugInfoWriteStream* stream) {
181 stream->write_int(CONSTANT_INT_CODE);
182 stream->write_signed_int(value());
183}
184
185void ConstantIntValue::print_on(outputStream* st) const {
186 st->print("%d", value());
187}
188
189// ConstantLongValue
190
191ConstantLongValue::ConstantLongValue(DebugInfoReadStream* stream) {
192 _value = stream->read_long();
193}
194
195void ConstantLongValue::write_on(DebugInfoWriteStream* stream) {
196 stream->write_int(CONSTANT_LONG_CODE);
197 stream->write_long(value());
198}
199
200void ConstantLongValue::print_on(outputStream* st) const {
201 st->print(JLONG_FORMAT, value());
202}
203
204// ConstantDoubleValue
205
206ConstantDoubleValue::ConstantDoubleValue(DebugInfoReadStream* stream) {
207 _value = stream->read_double();
208}
209
210void ConstantDoubleValue::write_on(DebugInfoWriteStream* stream) {
211 stream->write_int(CONSTANT_DOUBLE_CODE);
212 stream->write_double(value());
213}
214
215void ConstantDoubleValue::print_on(outputStream* st) const {
216 st->print("%f", value());
217}
218
219// ConstantOopWriteValue
220
221void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) {
222#ifdef ASSERT
223 {
224 // cannot use ThreadInVMfromNative here since in case of JVMCI compiler,
225 // thread is already in VM state.
226 ThreadInVMfromUnknown tiv;
227 assert(JNIHandles::resolve(value()) == NULL ||
228 Universe::heap()->is_in_reserved(JNIHandles::resolve(value())),
229 "Should be in heap");
230 }
231#endif
232 stream->write_int(CONSTANT_OOP_CODE);
233 stream->write_handle(value());
234}
235
236void ConstantOopWriteValue::print_on(outputStream* st) const {
237 // using ThreadInVMfromUnknown here since in case of JVMCI compiler,
238 // thread is already in VM state.
239 ThreadInVMfromUnknown tiv;
240 JNIHandles::resolve(value())->print_value_on(st);
241}
242
243
244// ConstantOopReadValue
245
246ConstantOopReadValue::ConstantOopReadValue(DebugInfoReadStream* stream) {
247 _value = Handle(Thread::current(), stream->read_oop());
248 assert(_value() == NULL ||
249 Universe::heap()->is_in_reserved(_value()), "Should be in heap");
250}
251
252void ConstantOopReadValue::write_on(DebugInfoWriteStream* stream) {
253 ShouldNotReachHere();
254}
255
256void ConstantOopReadValue::print_on(outputStream* st) const {
257 if (value()() != NULL) {
258 value()()->print_value_on(st);
259 } else {
260 st->print_cr("NULL");
261 }
262}
263
264
265// MonitorValue
266
267MonitorValue::MonitorValue(ScopeValue* owner, Location basic_lock, bool eliminated) {
268 _owner = owner;
269 _basic_lock = basic_lock;
270 _eliminated = eliminated;
271}
272
273MonitorValue::MonitorValue(DebugInfoReadStream* stream) {
274 _basic_lock = Location(stream);
275 _owner = ScopeValue::read_from(stream);
276 _eliminated = (stream->read_bool() != 0);
277}
278
279void MonitorValue::write_on(DebugInfoWriteStream* stream) {
280 _basic_lock.write_on(stream);
281 _owner->write_on(stream);
282 stream->write_bool(_eliminated);
283}
284
285#ifndef PRODUCT
286void MonitorValue::print_on(outputStream* st) const {
287 st->print("monitor{");
288 owner()->print_on(st);
289 st->print(",");
290 basic_lock().print_on(st);
291 st->print("}");
292 if (_eliminated) {
293 st->print(" (eliminated)");
294 }
295}
296#endif
297