7200163: add CodeComments functionality to assember stubs
Summary: Pass the codeBuffer to the Stub constructor, and adapts the disassembler to print the comments.
Reviewed-by: jrose, kvn, twisti
Contributed-by: goetz.lindenmaier@sap.com
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -1026,25 +1026,30 @@
}
return a;
}
+
+ // Convenience for add_comment.
+ CodeComment* find_last(intptr_t offset) {
+ CodeComment* a = find(offset);
+ if (a != NULL) {
+ while ((a->_next != NULL) && (a->_next->_offset == offset)) {
+ a = a->_next;
+ }
+ }
+ return a;
+ }
};
void CodeComments::add_comment(intptr_t offset, const char * comment) {
- CodeComment* c = new CodeComment(offset, comment);
- CodeComment* insert = NULL;
- if (_comments != NULL) {
- CodeComment* c = _comments->find(offset);
- insert = c;
- while (c && c->offset() == offset) {
- insert = c;
- c = c->next();
- }
- }
- if (insert) {
- // insert after comments with same offset
- c->set_next(insert->next());
- insert->set_next(c);
+ CodeComment* c = new CodeComment(offset, comment);
+ CodeComment* inspos = (_comments == NULL) ? NULL : _comments->find_last(offset);
+
+ if (inspos) {
+ // insert after already existing comments with same offset
+ c->set_next(inspos->next());
+ inspos->set_next(c);
} else {
+ // no comments with such offset, yet. Insert before anything else.
c->set_next(_comments);
_comments = c;
}
@@ -1052,12 +1057,11 @@
void CodeComments::assign(CodeComments& other) {
- assert(_comments == NULL, "don't overwrite old value");
_comments = other._comments;
}
-void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) {
+void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) const {
if (_comments != NULL) {
CodeComment* c = _comments->find(offset);
while (c && c->offset() == offset) {
@@ -1085,6 +1089,7 @@
void CodeBuffer::decode() {
+ ttyLocker ttyl;
Disassembler::decode(decode_begin(), insts_end());
_decode_begin = insts_end();
}
@@ -1096,6 +1101,7 @@
void CodeBuffer::decode_all() {
+ ttyLocker ttyl;
for (int n = 0; n < (int)SECT_LIMIT; n++) {
// dump contents of each section
CodeSection* cs = code_section(n);
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -253,7 +253,7 @@
}
void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
- void print_block_comment(outputStream* stream, intptr_t offset) PRODUCT_RETURN;
+ void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
void assign(CodeComments& other) PRODUCT_RETURN;
void free() PRODUCT_RETURN;
};
--- a/hotspot/src/share/vm/code/codeBlob.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -162,8 +162,10 @@
assert(strlen(name1) + strlen(name2) < sizeof(stub_id), "");
jio_snprintf(stub_id, sizeof(stub_id), "%s%s", name1, name2);
if (PrintStubCode) {
+ ttyLocker ttyl;
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, (intptr_t) stub);
Disassembler::decode(stub->code_begin(), stub->code_end());
+ tty->cr();
}
Forte::register_stub(stub_id, stub->code_begin(), stub->code_end());
@@ -548,6 +550,7 @@
}
void RuntimeStub::print_on(outputStream* st) const {
+ ttyLocker ttyl;
CodeBlob::print_on(st);
st->print("Runtime Stub (" INTPTR_FORMAT "): ", this);
st->print_cr(name());
@@ -563,6 +566,7 @@
}
void SingletonBlob::print_on(outputStream* st) const {
+ ttyLocker ttyl;
CodeBlob::print_on(st);
st->print_cr(name());
Disassembler::decode((CodeBlob*)this, st);
--- a/hotspot/src/share/vm/code/codeBlob.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/codeBlob.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -184,7 +184,7 @@
static void trace_new_stub(CodeBlob* blob, const char* name1, const char* name2 = "");
// Print the comment associated with offset on stream, if there is one
- virtual void print_block_comment(outputStream* stream, address block_begin) {
+ virtual void print_block_comment(outputStream* stream, address block_begin) const {
intptr_t offset = (intptr_t)(block_begin - code_begin());
_comments.print_block_comment(stream, offset);
}
--- a/hotspot/src/share/vm/code/icBuffer.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/icBuffer.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_CODE_ICBUFFER_HPP
#define SHARE_VM_CODE_ICBUFFER_HPP
+#include "asm/codeBuffer.hpp"
#include "code/stubs.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.hpp"
@@ -48,7 +49,8 @@
protected:
friend class ICStubInterface;
// This will be called only by ICStubInterface
- void initialize(int size) { _size = size; _ic_site = NULL; }
+ void initialize(int size,
+ CodeComments comments) { _size = size; _ic_site = NULL; }
void finalize(); // called when a method is removed
// General info
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -2672,7 +2672,7 @@
return NULL;
}
-void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) {
+void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) const {
if (block_begin == entry_point()) stream->print_cr("[Entry Point]");
if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]");
if (block_begin == exception_begin()) stream->print_cr("[Exception Handler]");
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/nmethod.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -653,11 +653,11 @@
void log_state_change() const;
// Prints block-level comments, including nmethod specific block labels:
- virtual void print_block_comment(outputStream* stream, address block_begin) {
+ virtual void print_block_comment(outputStream* stream, address block_begin) const {
print_nmethod_labels(stream, block_begin);
CodeBlob::print_block_comment(stream, block_begin);
}
- void print_nmethod_labels(outputStream* stream, address block_begin);
+ void print_nmethod_labels(outputStream* stream, address block_begin) const;
// Prints a comment for one native instruction (reloc info, pc desc)
void print_code_comment_on(outputStream* st, int column, address begin, address end);
--- a/hotspot/src/share/vm/code/stubs.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/stubs.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -101,7 +101,8 @@
Stub* StubQueue::request_committed(int code_size) {
Stub* s = request(code_size);
- if (s != NULL) commit(code_size);
+ CodeComments comments;
+ if (s != NULL) commit(code_size, comments);
return s;
}
@@ -118,7 +119,8 @@
assert(_buffer_limit == _buffer_size, "buffer must be fully usable");
if (_queue_end + requested_size <= _buffer_size) {
// code fits in at the end => nothing to do
- stub_initialize(s, requested_size);
+ CodeComments comments;
+ stub_initialize(s, requested_size, comments);
return s;
} else {
// stub doesn't fit in at the queue end
@@ -135,7 +137,8 @@
// Queue: |XXX|.......|XXXXXXX|.......|
// ^0 ^end ^begin ^limit ^size
s = current_stub();
- stub_initialize(s, requested_size);
+ CodeComments comments;
+ stub_initialize(s, requested_size, comments);
return s;
}
// Not enough space left
@@ -144,12 +147,12 @@
}
-void StubQueue::commit(int committed_code_size) {
+void StubQueue::commit(int committed_code_size, CodeComments& comments) {
assert(committed_code_size > 0, "committed_code_size must be > 0");
int committed_size = round_to(stub_code_size_to_size(committed_code_size), CodeEntryAlignment);
Stub* s = current_stub();
assert(committed_size <= stub_size(s), "committed size must not exceed requested size");
- stub_initialize(s, committed_size);
+ stub_initialize(s, committed_size, comments);
_queue_end += committed_size;
_number_of_stubs++;
if (_mutex != NULL) _mutex->unlock();
--- a/hotspot/src/share/vm/code/stubs.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/code/stubs.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_CODE_STUBS_HPP
#define SHARE_VM_CODE_STUBS_HPP
+#include "asm/codeBuffer.hpp"
#include "memory/allocation.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
@@ -71,7 +72,8 @@
class Stub VALUE_OBJ_CLASS_SPEC {
public:
// Initialization/finalization
- void initialize(int size) { ShouldNotCallThis(); } // called to initialize/specify the stub's size
+ void initialize(int size,
+ CodeComments& comments) { ShouldNotCallThis(); } // called to initialize/specify the stub's size
void finalize() { ShouldNotCallThis(); } // called before the stub is deallocated
// General info/converters
@@ -104,7 +106,8 @@
class StubInterface: public CHeapObj<mtCode> {
public:
// Initialization/finalization
- virtual void initialize(Stub* self, int size) = 0; // called after creation (called twice if allocated via (request, commit))
+ virtual void initialize(Stub* self, int size,
+ CodeComments& comments) = 0; // called after creation (called twice if allocated via (request, commit))
virtual void finalize(Stub* self) = 0; // called before deallocation
// General info/converters
@@ -132,7 +135,8 @@
\
public: \
/* Initialization/finalization */ \
- virtual void initialize(Stub* self, int size) { cast(self)->initialize(size); } \
+ virtual void initialize(Stub* self, int size, \
+ CodeComments& comments) { cast(self)->initialize(size, comments); } \
virtual void finalize(Stub* self) { cast(self)->finalize(); } \
\
/* General info */ \
@@ -171,7 +175,8 @@
Stub* current_stub() const { return stub_at(_queue_end); }
// Stub functionality accessed via interface
- void stub_initialize(Stub* s, int size) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size); }
+ void stub_initialize(Stub* s, int size,
+ CodeComments& comments) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, comments); }
void stub_finalize(Stub* s) { _stub_interface->finalize(s); }
int stub_size(Stub* s) const { return _stub_interface->size(s); }
bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
@@ -200,7 +205,8 @@
// Stub allocation (atomic transactions)
Stub* request_committed(int code_size); // request a stub that provides exactly code_size space for code
Stub* request(int requested_code_size); // request a stub with a (maximum) code space - locks the queue
- void commit (int committed_code_size); // commit the previously requested stub - unlocks the queue
+ void commit (int committed_code_size,
+ CodeComments& comments); // commit the previously requested stub - unlocks the queue
// Stub deallocation
void remove_first(); // remove the first stub in the queue
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -148,6 +148,7 @@
private:
nmethod* _nm;
CodeBlob* _code;
+ CodeComments _comments;
outputStream* _output;
address _start, _end;
@@ -187,7 +188,7 @@
void print_address(address value);
public:
- decode_env(CodeBlob* code, outputStream* output);
+ decode_env(CodeBlob* code, outputStream* output, CodeComments c = CodeComments());
address decode_instructions(address start, address end);
@@ -229,12 +230,13 @@
const char* options() { return _option_buf; }
};
-decode_env::decode_env(CodeBlob* code, outputStream* output) {
+decode_env::decode_env(CodeBlob* code, outputStream* output, CodeComments c) {
memset(this, 0, sizeof(*this));
_output = output ? output : tty;
_code = code;
if (code != NULL && code->is_nmethod())
_nm = (nmethod*) code;
+ _comments.assign(c);
// by default, output pc but not bytes:
_print_pc = true;
@@ -356,6 +358,7 @@
if (cb != NULL) {
cb->print_block_comment(st, p);
}
+ _comments.print_block_comment(st, (intptr_t)(p - _start));
if (_print_pc) {
st->print(" " PTR_FORMAT ": ", p);
}
@@ -467,10 +470,9 @@
env.decode_instructions(cb->code_begin(), cb->code_end());
}
-
-void Disassembler::decode(address start, address end, outputStream* st) {
+void Disassembler::decode(address start, address end, outputStream* st, CodeComments c) {
if (!load_library()) return;
- decode_env env(CodeCache::find_blob_unsafe(start), st);
+ decode_env env(CodeCache::find_blob_unsafe(start), st, c);
env.decode_instructions(start, end);
}
--- a/hotspot/src/share/vm/compiler/disassembler.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/compiler/disassembler.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_COMPILER_DISASSEMBLER_HPP
#define SHARE_VM_COMPILER_DISASSEMBLER_HPP
+#include "asm/codeBuffer.hpp"
#include "runtime/globals.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
@@ -87,7 +88,7 @@
}
static void decode(CodeBlob *cb, outputStream* st = NULL);
static void decode(nmethod* nm, outputStream* st = NULL);
- static void decode(address begin, address end, outputStream* st = NULL);
+ static void decode(address begin, address end, outputStream* st = NULL, CodeComments c = CodeComments());
};
#endif // SHARE_VM_COMPILER_DISASSEMBLER_HPP
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -60,6 +60,8 @@
void InterpreterCodelet::print_on(outputStream* st) const {
+ ttyLocker ttyl;
+
if (PrintInterpreter) {
st->cr();
st->print_cr("----------------------------------------------------------------------");
@@ -72,7 +74,7 @@
if (PrintInterpreter) {
st->cr();
- Disassembler::decode(code_begin(), code_end(), st);
+ Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_comments) NOT_DEBUG(CodeComments()));
}
}
--- a/hotspot/src/share/vm/interpreter/interpreter.hpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreter.hpp Mon Sep 24 10:30:14 2012 -0700
@@ -48,10 +48,12 @@
int _size; // the size in bytes
const char* _description; // a description of the codelet, for debugging & printing
Bytecodes::Code _bytecode; // associated bytecode if any
+ DEBUG_ONLY(CodeComments _comments;) // Comments for annotating assembler output.
public:
// Initialization/finalization
- void initialize(int size) { _size = size; }
+ void initialize(int size,
+ CodeComments& comments) { _size = size; DEBUG_ONLY(_comments.assign(comments);) }
void finalize() { ShouldNotCallThis(); }
// General info/converters
@@ -129,7 +131,7 @@
// commit Codelet
- AbstractInterpreter::code()->commit((*_masm)->code()->pure_insts_size());
+ AbstractInterpreter::code()->commit((*_masm)->code()->pure_insts_size(), (*_masm)->code()->comments());
// make sure nobody can use _masm outside a CodeletMark lifespan
*_masm = NULL;
}
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Sep 20 16:49:17 2012 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Sep 24 10:30:14 2012 -0700
@@ -2460,6 +2460,7 @@
#ifndef PRODUCT
// debugging suppport
if (PrintAdapterHandlers || PrintStubCode) {
+ ttyLocker ttyl;
entry->print_adapter_on(tty);
tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)",
_adapters->number_of_entries(), (method->is_static() ? "static" : "receiver"),
@@ -2467,8 +2468,10 @@
tty->print_cr("c2i argument handler starts at %p",entry->get_c2i_entry());
if (Verbose || PrintStubCode) {
address first_pc = entry->base_address();
- if (first_pc != NULL)
+ if (first_pc != NULL) {
Disassembler::decode(first_pc, first_pc + insts_size);
+ tty->cr();
+ }
}
}
#endif