duke@435: /* coleenp@6628: * Copyright (c) 1997, 2014, 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: #ifndef SHARE_VM_CODE_DEBUGINFO_HPP stefank@2314: #define SHARE_VM_CODE_DEBUGINFO_HPP stefank@2314: stefank@2314: #include "code/compressedStream.hpp" stefank@2314: #include "code/location.hpp" stefank@2314: #include "code/nmethod.hpp" stefank@2314: #include "code/oopRecorder.hpp" stefank@2314: #include "runtime/stackValue.hpp" stefank@2314: #include "utilities/growableArray.hpp" stefank@2314: duke@435: // Classes used for serializing debugging information. duke@435: // These abstractions are introducted to provide symmetric duke@435: // read and write operations. duke@435: duke@435: // ScopeValue describes the value of a variable/expression in a scope duke@435: // - LocationValue describes a value in a given location (in frame or register) duke@435: // - ConstantValue describes a constant duke@435: coleenp@4037: class ConstantOopReadValue; coleenp@4037: duke@435: class ScopeValue: public ResourceObj { duke@435: public: duke@435: // Testers duke@435: virtual bool is_location() const { return false; } duke@435: virtual bool is_object() const { return false; } duke@435: virtual bool is_constant_int() const { return false; } duke@435: virtual bool is_constant_double() const { return false; } duke@435: virtual bool is_constant_long() const { return false; } duke@435: virtual bool is_constant_oop() const { return false; } duke@435: virtual bool equals(ScopeValue* other) const { return false; } duke@435: coleenp@4037: ConstantOopReadValue* as_ConstantOopReadValue() { coleenp@4037: assert(is_constant_oop(), "must be"); coleenp@4037: return (ConstantOopReadValue*) this; coleenp@4037: } coleenp@4037: duke@435: // Serialization of debugging information duke@435: virtual void write_on(DebugInfoWriteStream* stream) = 0; duke@435: static ScopeValue* read_from(DebugInfoReadStream* stream); duke@435: }; duke@435: duke@435: duke@435: // A Location value describes a value in a given location; i.e. the corresponding duke@435: // logical entity (e.g., a method temporary) lives in this location. duke@435: duke@435: class LocationValue: public ScopeValue { duke@435: private: duke@435: Location _location; duke@435: public: duke@435: LocationValue(Location location) { _location = location; } duke@435: bool is_location() const { return true; } duke@435: Location location() const { return _location; } duke@435: duke@435: // Serialization of debugging information duke@435: LocationValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: duke@435: // An ObjectValue describes an object eliminated by escape analysis. duke@435: duke@435: class ObjectValue: public ScopeValue { duke@435: private: duke@435: int _id; duke@435: ScopeValue* _klass; duke@435: GrowableArray _field_values; duke@435: Handle _value; duke@435: bool _visited; duke@435: duke@435: public: duke@435: ObjectValue(int id, ScopeValue* klass) duke@435: : _id(id) duke@435: , _klass(klass) duke@435: , _field_values() duke@435: , _value() duke@435: , _visited(false) { coleenp@4037: assert(klass->is_constant_oop(), "should be constant java mirror oop"); duke@435: } duke@435: duke@435: ObjectValue(int id) duke@435: : _id(id) duke@435: , _klass(NULL) duke@435: , _field_values() duke@435: , _value() duke@435: , _visited(false) {} duke@435: duke@435: // Accessors duke@435: bool is_object() const { return true; } duke@435: int id() const { return _id; } duke@435: ScopeValue* klass() const { return _klass; } duke@435: GrowableArray* field_values() { return &_field_values; } duke@435: ScopeValue* field_at(int i) const { return _field_values.at(i); } duke@435: int field_size() { return _field_values.length(); } duke@435: Handle value() const { return _value; } duke@435: bool is_visited() const { return _visited; } duke@435: duke@435: void set_value(oop value) { _value = Handle(value); } duke@435: void set_visited(bool visited) { _visited = false; } duke@435: duke@435: // Serialization of debugging information duke@435: void read_object(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: void print_fields_on(outputStream* st) const; duke@435: }; duke@435: duke@435: duke@435: // A ConstantIntValue describes a constant int; i.e., the corresponding logical entity duke@435: // is either a source constant or its computation has been constant-folded. duke@435: duke@435: class ConstantIntValue: public ScopeValue { duke@435: private: duke@435: jint _value; duke@435: public: duke@435: ConstantIntValue(jint value) { _value = value; } duke@435: jint value() const { return _value; } duke@435: bool is_constant_int() const { return true; } duke@435: bool equals(ScopeValue* other) const { return false; } duke@435: duke@435: // Serialization of debugging information duke@435: ConstantIntValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: class ConstantLongValue: public ScopeValue { duke@435: private: duke@435: jlong _value; duke@435: public: duke@435: ConstantLongValue(jlong value) { _value = value; } duke@435: jlong value() const { return _value; } duke@435: bool is_constant_long() const { return true; } duke@435: bool equals(ScopeValue* other) const { return false; } duke@435: duke@435: // Serialization of debugging information duke@435: ConstantLongValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: class ConstantDoubleValue: public ScopeValue { duke@435: private: duke@435: jdouble _value; duke@435: public: duke@435: ConstantDoubleValue(jdouble value) { _value = value; } duke@435: jdouble value() const { return _value; } duke@435: bool is_constant_double() const { return true; } duke@435: bool equals(ScopeValue* other) const { return false; } duke@435: duke@435: // Serialization of debugging information duke@435: ConstantDoubleValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: // A ConstantOopWriteValue is created by the compiler to duke@435: // be written as debugging information. duke@435: duke@435: class ConstantOopWriteValue: public ScopeValue { duke@435: private: duke@435: jobject _value; duke@435: public: duke@435: ConstantOopWriteValue(jobject value) { _value = value; } duke@435: jobject value() const { return _value; } duke@435: bool is_constant_oop() const { return true; } duke@435: bool equals(ScopeValue* other) const { return false; } duke@435: duke@435: // Serialization of debugging information duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: // A ConstantOopReadValue is created by the VM when reading duke@435: // debug information duke@435: duke@435: class ConstantOopReadValue: public ScopeValue { duke@435: private: duke@435: Handle _value; duke@435: public: duke@435: Handle value() const { return _value; } duke@435: bool is_constant_oop() const { return true; } duke@435: bool equals(ScopeValue* other) const { return false; } duke@435: duke@435: // Serialization of debugging information duke@435: ConstantOopReadValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: // MonitorValue describes the pair used for monitor_enter and monitor_exit. duke@435: duke@435: class MonitorValue: public ResourceObj { duke@435: private: duke@435: ScopeValue* _owner; duke@435: Location _basic_lock; duke@435: bool _eliminated; duke@435: public: duke@435: // Constructor duke@435: MonitorValue(ScopeValue* owner, Location basic_lock, bool eliminated = false); duke@435: duke@435: // Accessors duke@435: ScopeValue* owner() const { return _owner; } duke@435: Location basic_lock() const { return _basic_lock; } duke@435: bool eliminated() const { return _eliminated; } duke@435: duke@435: // Serialization of debugging information duke@435: MonitorValue(DebugInfoReadStream* stream); duke@435: void write_on(DebugInfoWriteStream* stream); duke@435: duke@435: // Printing duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: // DebugInfoReadStream specializes CompressedReadStream for reading duke@435: // debugging information. Used by ScopeDesc. duke@435: duke@435: class DebugInfoReadStream : public CompressedReadStream { duke@435: private: duke@435: const nmethod* _code; duke@435: const nmethod* code() const { return _code; } duke@435: GrowableArray* _obj_pool; duke@435: public: duke@435: DebugInfoReadStream(const nmethod* code, int offset, GrowableArray* obj_pool = NULL) : duke@435: CompressedReadStream(code->scopes_data_begin(), offset) { duke@435: _code = code; duke@435: _obj_pool = obj_pool; duke@435: duke@435: } ; duke@435: duke@435: oop read_oop() { coleenp@4037: oop o = code()->oop_at(read_int()); coleenp@4037: assert(o == NULL || o->is_oop(), "oop only"); coleenp@4037: return o; coleenp@4037: } coleenp@4037: Method* read_method() { coleenp@4037: Method* o = (Method*)(code()->metadata_at(read_int())); coleenp@6628: // is_metadata() is a faster check than is_metaspace_object() coleenp@6628: assert(o == NULL || o->is_metadata(), "meta data only"); coleenp@4037: return o; duke@435: } duke@435: ScopeValue* read_object_value(); duke@435: ScopeValue* get_cached_object(); duke@435: // BCI encoding is mostly unsigned, but -1 is a distinguished value cfang@1366: int read_bci() { return read_int() + InvocationEntryBci; } duke@435: }; duke@435: duke@435: // DebugInfoWriteStream specializes CompressedWriteStream for duke@435: // writing debugging information. Used by ScopeDescRecorder. duke@435: duke@435: class DebugInfoWriteStream : public CompressedWriteStream { duke@435: private: duke@435: DebugInformationRecorder* _recorder; duke@435: DebugInformationRecorder* recorder() const { return _recorder; } duke@435: public: duke@435: DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size); duke@435: void write_handle(jobject h); cfang@1366: void write_bci(int bci) { write_int(bci - InvocationEntryBci); } coleenp@4037: coleenp@4037: void write_metadata(Metadata* m); duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_CODE_DEBUGINFO_HPP