# HG changeset patch # User kvn # Date 1348507814 25200 # Node ID 89b873bcc55b7b64296aeff222692d6264ff9d94 # Parent 8d82c4dfa72240a97bbbd81962a8362c55f42e69 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 diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/asm/codeBuffer.cpp --- 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); diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/asm/codeBuffer.hpp --- 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; }; diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/codeBlob.cpp --- 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); diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/codeBlob.hpp --- 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); } diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/icBuffer.hpp --- 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 diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/nmethod.cpp --- 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]"); diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/nmethod.hpp --- 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); diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/stubs.cpp --- 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(); diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/code/stubs.hpp --- 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 { 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 diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/compiler/disassembler.cpp --- 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); } diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/compiler/disassembler.hpp --- 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 diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/interpreter/interpreter.cpp --- 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())); } } diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/interpreter/interpreter.hpp --- 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; } diff -r 8d82c4dfa722 -r 89b873bcc55b hotspot/src/share/vm/runtime/sharedRuntime.cpp --- 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