duke@435: /* coleenp@4037: * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "code/debugInfo.hpp" stefank@2314: #include "code/debugInfoRec.hpp" stefank@2314: #include "code/nmethod.hpp" stefank@2314: #include "runtime/handles.inline.hpp" duke@435: duke@435: // Comstructors duke@435: duke@435: DebugInfoWriteStream::DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size) duke@435: : CompressedWriteStream(initial_size) { duke@435: _recorder = recorder; duke@435: } duke@435: duke@435: // Serializing oops duke@435: duke@435: void DebugInfoWriteStream::write_handle(jobject h) { duke@435: write_int(recorder()->oop_recorder()->find_index(h)); duke@435: } duke@435: coleenp@4037: void DebugInfoWriteStream::write_metadata(Metadata* h) { coleenp@4037: write_int(recorder()->oop_recorder()->find_index(h)); coleenp@4037: } coleenp@4037: duke@435: ScopeValue* DebugInfoReadStream::read_object_value() { duke@435: int id = read_int(); duke@435: #ifdef ASSERT duke@435: assert(_obj_pool != NULL, "object pool does not exist"); duke@435: for (int i = _obj_pool->length() - 1; i >= 0; i--) { duke@435: assert(((ObjectValue*) _obj_pool->at(i))->id() != id, "should not be read twice"); duke@435: } duke@435: #endif duke@435: ObjectValue* result = new ObjectValue(id); kvn@479: // Cache the object since an object field could reference it. kvn@479: _obj_pool->push(result); duke@435: result->read_object(this); duke@435: return result; duke@435: } duke@435: duke@435: ScopeValue* DebugInfoReadStream::get_cached_object() { duke@435: int id = read_int(); duke@435: assert(_obj_pool != NULL, "object pool does not exist"); duke@435: for (int i = _obj_pool->length() - 1; i >= 0; i--) { kvn@479: ObjectValue* ov = (ObjectValue*) _obj_pool->at(i); kvn@479: if (ov->id() == id) { kvn@479: return ov; duke@435: } duke@435: } duke@435: ShouldNotReachHere(); duke@435: return NULL; duke@435: } duke@435: duke@435: // Serializing scope values duke@435: duke@435: enum { LOCATION_CODE = 0, CONSTANT_INT_CODE = 1, CONSTANT_OOP_CODE = 2, duke@435: CONSTANT_LONG_CODE = 3, CONSTANT_DOUBLE_CODE = 4, duke@435: OBJECT_CODE = 5, OBJECT_ID_CODE = 6 }; duke@435: duke@435: ScopeValue* ScopeValue::read_from(DebugInfoReadStream* stream) { duke@435: ScopeValue* result = NULL; duke@435: switch(stream->read_int()) { duke@435: case LOCATION_CODE: result = new LocationValue(stream); break; duke@435: case CONSTANT_INT_CODE: result = new ConstantIntValue(stream); break; duke@435: case CONSTANT_OOP_CODE: result = new ConstantOopReadValue(stream); break; duke@435: case CONSTANT_LONG_CODE: result = new ConstantLongValue(stream); break; duke@435: case CONSTANT_DOUBLE_CODE: result = new ConstantDoubleValue(stream); break; duke@435: case OBJECT_CODE: result = stream->read_object_value(); break; duke@435: case OBJECT_ID_CODE: result = stream->get_cached_object(); break; duke@435: default: ShouldNotReachHere(); duke@435: } duke@435: return result; duke@435: } duke@435: duke@435: // LocationValue duke@435: duke@435: LocationValue::LocationValue(DebugInfoReadStream* stream) { duke@435: _location = Location(stream); duke@435: } duke@435: duke@435: void LocationValue::write_on(DebugInfoWriteStream* stream) { duke@435: stream->write_int(LOCATION_CODE); duke@435: location().write_on(stream); duke@435: } duke@435: duke@435: void LocationValue::print_on(outputStream* st) const { duke@435: location().print_on(st); duke@435: } duke@435: duke@435: // ObjectValue duke@435: duke@435: void ObjectValue::read_object(DebugInfoReadStream* stream) { duke@435: _klass = read_from(stream); coleenp@4037: assert(_klass->is_constant_oop(), "should be constant java mirror oop"); duke@435: int length = stream->read_int(); duke@435: for (int i = 0; i < length; i++) { duke@435: ScopeValue* val = read_from(stream); duke@435: _field_values.append(val); duke@435: } duke@435: } duke@435: duke@435: void ObjectValue::write_on(DebugInfoWriteStream* stream) { duke@435: if (_visited) { duke@435: stream->write_int(OBJECT_ID_CODE); duke@435: stream->write_int(_id); duke@435: } else { duke@435: _visited = true; duke@435: stream->write_int(OBJECT_CODE); duke@435: stream->write_int(_id); duke@435: _klass->write_on(stream); duke@435: int length = _field_values.length(); duke@435: stream->write_int(length); duke@435: for (int i = 0; i < length; i++) { duke@435: _field_values.at(i)->write_on(stream); duke@435: } duke@435: } duke@435: } duke@435: duke@435: void ObjectValue::print_on(outputStream* st) const { duke@435: st->print("obj[%d]", _id); duke@435: } duke@435: duke@435: void ObjectValue::print_fields_on(outputStream* st) const { duke@435: #ifndef PRODUCT duke@435: if (_field_values.length() > 0) { duke@435: _field_values.at(0)->print_on(st); duke@435: } duke@435: for (int i = 1; i < _field_values.length(); i++) { duke@435: st->print(", "); duke@435: _field_values.at(i)->print_on(st); duke@435: } duke@435: #endif duke@435: } duke@435: duke@435: // ConstantIntValue duke@435: duke@435: ConstantIntValue::ConstantIntValue(DebugInfoReadStream* stream) { duke@435: _value = stream->read_signed_int(); duke@435: } duke@435: duke@435: void ConstantIntValue::write_on(DebugInfoWriteStream* stream) { duke@435: stream->write_int(CONSTANT_INT_CODE); duke@435: stream->write_signed_int(value()); duke@435: } duke@435: duke@435: void ConstantIntValue::print_on(outputStream* st) const { duke@435: st->print("%d", value()); duke@435: } duke@435: duke@435: // ConstantLongValue duke@435: duke@435: ConstantLongValue::ConstantLongValue(DebugInfoReadStream* stream) { duke@435: _value = stream->read_long(); duke@435: } duke@435: duke@435: void ConstantLongValue::write_on(DebugInfoWriteStream* stream) { duke@435: stream->write_int(CONSTANT_LONG_CODE); duke@435: stream->write_long(value()); duke@435: } duke@435: duke@435: void ConstantLongValue::print_on(outputStream* st) const { duke@435: st->print(INT64_FORMAT, value()); duke@435: } duke@435: duke@435: // ConstantDoubleValue duke@435: duke@435: ConstantDoubleValue::ConstantDoubleValue(DebugInfoReadStream* stream) { duke@435: _value = stream->read_double(); duke@435: } duke@435: duke@435: void ConstantDoubleValue::write_on(DebugInfoWriteStream* stream) { duke@435: stream->write_int(CONSTANT_DOUBLE_CODE); duke@435: stream->write_double(value()); duke@435: } duke@435: duke@435: void ConstantDoubleValue::print_on(outputStream* st) const { duke@435: st->print("%f", value()); duke@435: } duke@435: duke@435: // ConstantOopWriteValue duke@435: duke@435: void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) { coleenp@4037: assert(JNIHandles::resolve(value()) == NULL || coleenp@4037: Universe::heap()->is_in_reserved(JNIHandles::resolve(value())), coleenp@4037: "Should be in heap"); duke@435: stream->write_int(CONSTANT_OOP_CODE); duke@435: stream->write_handle(value()); duke@435: } duke@435: duke@435: void ConstantOopWriteValue::print_on(outputStream* st) const { duke@435: JNIHandles::resolve(value())->print_value_on(st); duke@435: } duke@435: duke@435: duke@435: // ConstantOopReadValue duke@435: duke@435: ConstantOopReadValue::ConstantOopReadValue(DebugInfoReadStream* stream) { duke@435: _value = Handle(stream->read_oop()); coleenp@4037: assert(_value() == NULL || coleenp@4037: Universe::heap()->is_in_reserved(_value()), "Should be in heap"); duke@435: } duke@435: duke@435: void ConstantOopReadValue::write_on(DebugInfoWriteStream* stream) { duke@435: ShouldNotReachHere(); duke@435: } duke@435: duke@435: void ConstantOopReadValue::print_on(outputStream* st) const { duke@435: value()()->print_value_on(st); duke@435: } duke@435: duke@435: duke@435: // MonitorValue duke@435: duke@435: MonitorValue::MonitorValue(ScopeValue* owner, Location basic_lock, bool eliminated) { duke@435: _owner = owner; duke@435: _basic_lock = basic_lock; duke@435: _eliminated = eliminated; duke@435: } duke@435: duke@435: MonitorValue::MonitorValue(DebugInfoReadStream* stream) { duke@435: _basic_lock = Location(stream); duke@435: _owner = ScopeValue::read_from(stream); duke@435: _eliminated = (stream->read_bool() != 0); duke@435: } duke@435: duke@435: void MonitorValue::write_on(DebugInfoWriteStream* stream) { duke@435: _basic_lock.write_on(stream); duke@435: _owner->write_on(stream); duke@435: stream->write_bool(_eliminated); duke@435: } duke@435: duke@435: #ifndef PRODUCT duke@435: void MonitorValue::print_on(outputStream* st) const { duke@435: st->print("monitor{"); duke@435: owner()->print_on(st); duke@435: st->print(","); duke@435: basic_lock().print_on(st); duke@435: st->print("}"); duke@435: if (_eliminated) { duke@435: st->print(" (eliminated)"); duke@435: } duke@435: } duke@435: #endif