< prev index next > src/hotspot/share/asm/codeBuffer.cpp
Print this page
#include "code/compiledIC.hpp"
#include "code/oopRecorder.inline.hpp"
#include "compiler/disassembler.hpp"
#include "logging/log.hpp"
#include "oops/klass.inline.hpp"
+ #include "oops/methodCounters.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/icache.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "utilities/align.hpp"
Metadata* m = md->metadata_value();
if (oop_recorder()->is_real(m)) {
if (m->is_methodData()) {
m = ((MethodData*)m)->method();
}
+ if (m->is_methodCounters()) {
+ m = ((MethodCounters*)m)->method();
+ }
if (m->is_method()) {
m = ((Method*)m)->method_holder();
}
if (m->is_klass()) {
append_oop_references(&oops, (Klass*)m);
Metadata* m = oop_recorder()->metadata_at(i);
if (oop_recorder()->is_real(m)) {
if (m->is_methodData()) {
m = ((MethodData*)m)->method();
}
+ if (m->is_methodCounters()) {
+ m = ((MethodCounters*)m)->method();
+ }
if (m->is_method()) {
m = ((Method*)m)->method_holder();
}
if (m->is_klass()) {
append_oop_references(&oops, (Klass*)m);
void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
#ifndef PRODUCT
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("done with CodeBuffer:");
! ((CodeBuffer*)this)->print();
}
#endif //PRODUCT
CodeBuffer dest(dest_blob);
assert(dest_blob->content_size() >= total_content_size(), "good sizing");
void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
#ifndef PRODUCT
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("done with CodeBuffer:");
! ((CodeBuffer*)this)->print_on(tty);
}
#endif //PRODUCT
CodeBuffer dest(dest_blob);
assert(dest_blob->content_size() >= total_content_size(), "good sizing");
void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
#ifndef PRODUCT
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("expanding CodeBuffer:");
! this->print();
}
if (StressCodeBuffers && blob() != nullptr) {
static int expand_count = 0;
if (expand_count >= 0) expand_count += 1;
void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
#ifndef PRODUCT
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("expanding CodeBuffer:");
! this->print_on(tty);
}
if (StressCodeBuffers && blob() != nullptr) {
static int expand_count = 0;
if (expand_count >= 0) expand_count += 1;
#ifndef PRODUCT
_decode_begin = nullptr; // sanity
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("expanded CodeBuffer:");
! this->print();
}
#endif //PRODUCT
}
void CodeBuffer::adjust_internal_address(address from, address to) {
#ifndef PRODUCT
_decode_begin = nullptr; // sanity
if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("expanded CodeBuffer:");
! this->print_on(tty);
}
#endif //PRODUCT
}
void CodeBuffer::adjust_internal_address(address from, address to) {
if (!other->is_allocated() || other == sect) {
continue;
}
guarantee(other->disjoint(sect), "sanity");
}
! guarantee(sect->end() <= tend, "sanity");
! guarantee(sect->end() <= sect->limit(), "sanity");
}
}
void CodeBuffer::log_section_sizes(const char* name) {
if (xtty != nullptr) {
ttyLocker ttyl;
// log info about buffer usage
! xtty->print_cr("<blob name='%s' total_size='%d'>", name, _total_size);
for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
CodeSection* sect = code_section(n);
if (!sect->is_allocated() || sect->is_empty()) continue;
! xtty->print_cr("<sect index='%d' capacity='%d' size='%d' remaining='%d'/>",
! n, sect->capacity(), sect->size(), sect->remaining());
}
! xtty->print_cr("</blob>");
}
}
bool CodeBuffer::finalize_stubs() {
if (_finalize_stubs && !pd_finalize_stubs()) {
if (!other->is_allocated() || other == sect) {
continue;
}
guarantee(other->disjoint(sect), "sanity");
}
! guarantee(sect->end() <= tend, "sanity, sect_end: " PTR_FORMAT " tend: " PTR_FORMAT " size: %d", p2i(sect->end()), p2i(tend), (int)_total_size);
! guarantee(sect->end() <= sect->limit(), "sanity, sect_end: " PTR_FORMAT " sect_limit: " PTR_FORMAT, p2i(sect->end()), p2i(sect->limit()));
}
}
void CodeBuffer::log_section_sizes(const char* name) {
if (xtty != nullptr) {
ttyLocker ttyl;
// log info about buffer usage
! xtty->head("blob name='%s' total_size='%d'", name, _total_size);
for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
CodeSection* sect = code_section(n);
if (!sect->is_allocated() || sect->is_empty()) continue;
! xtty->elem("sect index='%d' capacity='%d' size='%d' remaining='%d'",
! n, sect->capacity(), sect->size(), sect->remaining());
}
! xtty->tail("blob");
}
}
bool CodeBuffer::finalize_stubs() {
if (_finalize_stubs && !pd_finalize_stubs()) {
ttyLocker ttyl;
Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &asm_remarks()));
_decode_begin = insts_end();
}
! void CodeSection::print(const char* name) {
csize_t locs_size = locs_end() - locs_start();
! tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)",
! name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity());
! tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
! name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
if (PrintRelocations && (locs_size != 0)) {
RelocIterator iter(this);
! iter.print();
}
}
! void CodeBuffer::print() {
! tty->print_cr("CodeBuffer:");
for (int n = 0; n < (int)SECT_LIMIT; n++) {
// print each section
CodeSection* cs = code_section(n);
! cs->print(code_section_name(n));
}
}
- // ----- CHeapString -----------------------------------------------------------
-
- class CHeapString : public CHeapObj<mtCode> {
- public:
- CHeapString(const char* str) : _string(os::strdup(str)) {}
- ~CHeapString() {
- os::free((void*)_string);
- _string = nullptr;
- }
- const char* string() const { return _string; }
-
- private:
- const char* _string;
- };
-
- // ----- AsmRemarkCollection ---------------------------------------------------
-
- class AsmRemarkCollection : public CHeapObj<mtCode> {
- public:
- AsmRemarkCollection() : _ref_cnt(1), _remarks(nullptr), _next(nullptr) {}
- ~AsmRemarkCollection() {
- assert(is_empty(), "Must 'clear()' before deleting!");
- assert(_ref_cnt == 0, "No uses must remain when deleting!");
- }
- AsmRemarkCollection* reuse() {
- precond(_ref_cnt > 0);
- return _ref_cnt++, this;
- }
-
- const char* insert(uint offset, const char* remark);
- const char* lookup(uint offset) const;
- const char* next(uint offset) const;
-
- bool is_empty() const { return _remarks == nullptr; }
- uint clear();
-
- private:
- struct Cell : CHeapString {
- Cell(const char* remark, uint offset) :
- CHeapString(remark), offset(offset), prev(nullptr), next(nullptr) {}
- void push_back(Cell* cell) {
- Cell* head = this;
- Cell* tail = prev;
- tail->next = cell;
- cell->next = head;
- cell->prev = tail;
- prev = cell;
- }
- uint offset;
- Cell* prev;
- Cell* next;
- };
- uint _ref_cnt;
- Cell* _remarks;
- // Using a 'mutable' iteration pointer to allow 'const' on lookup/next (that
- // does not change the state of the list per se), supportig a simplistic
- // iteration scheme.
- mutable Cell* _next;
- };
-
- // ----- DbgStringCollection ---------------------------------------------------
-
- class DbgStringCollection : public CHeapObj<mtCode> {
- public:
- DbgStringCollection() : _ref_cnt(1), _strings(nullptr) {}
- ~DbgStringCollection() {
- assert(is_empty(), "Must 'clear()' before deleting!");
- assert(_ref_cnt == 0, "No uses must remain when deleting!");
- }
- DbgStringCollection* reuse() {
- precond(_ref_cnt > 0);
- return _ref_cnt++, this;
- }
-
- const char* insert(const char* str);
- const char* lookup(const char* str) const;
-
- bool is_empty() const { return _strings == nullptr; }
- uint clear();
-
- private:
- struct Cell : CHeapString {
- Cell(const char* dbgstr) :
- CHeapString(dbgstr), prev(nullptr), next(nullptr) {}
- void push_back(Cell* cell) {
- Cell* head = this;
- Cell* tail = prev;
- tail->next = cell;
- cell->next = head;
- cell->prev = tail;
- prev = cell;
- }
- Cell* prev;
- Cell* next;
- };
- uint _ref_cnt;
- Cell* _strings;
- };
-
// ----- AsmRemarks ------------------------------------------------------------
//
// Acting as interface to reference counted mapping [offset -> remark], where
// offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or
// other memory buffer) and remark is a string (comment).
ttyLocker ttyl;
Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &asm_remarks()));
_decode_begin = insts_end();
}
! void CodeSection::print_on(outputStream* st, const char* name) {
csize_t locs_size = locs_end() - locs_start();
! st->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)",
! name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity());
! st->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
! name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
if (PrintRelocations && (locs_size != 0)) {
RelocIterator iter(this);
! iter.print_on(st);
}
}
! void CodeBuffer::print_on(outputStream* st) {
! #if 0
+ if (this == nullptr) { // gcc complains 'nonnull' argument 'this' compared to nullptr
+ st->print_cr("null CodeBuffer pointer");
+ return;
+ }
+ #endif
+
+ st->print_cr("CodeBuffer:%s", name());
for (int n = 0; n < (int)SECT_LIMIT; n++) {
// print each section
CodeSection* cs = code_section(n);
! cs->print_on(st, code_section_name(n));
}
}
// ----- AsmRemarks ------------------------------------------------------------
//
// Acting as interface to reference counted mapping [offset -> remark], where
// offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or
// other memory buffer) and remark is a string (comment).
AsmRemarks::AsmRemarks() : _remarks(new AsmRemarkCollection()) {
assert(_remarks != nullptr, "Allocation failure!");
}
AsmRemarks::~AsmRemarks() {
+ if (_remarks != nullptr) {
+ clear();
+ }
assert(_remarks == nullptr, "Must 'clear()' before deleting!");
}
+ void AsmRemarks::init(AsmRemarks& asm_remarks) {
+ asm_remarks._remarks = new AsmRemarkCollection();
+ }
+
const char* AsmRemarks::insert(uint offset, const char* remstr) {
precond(remstr != nullptr);
return _remarks->insert(offset, remstr);
}
clear();
_remarks = src._remarks->reuse();
}
void AsmRemarks::clear() {
+ assert(_remarks != nullptr, "sanity check");
if (_remarks->clear() == 0) {
delete _remarks;
}
_remarks = nullptr;
}
DbgStrings::DbgStrings() : _strings(new DbgStringCollection()) {
assert(_strings != nullptr, "Allocation failure!");
}
DbgStrings::~DbgStrings() {
+ if (_strings != nullptr) {
+ clear();
+ }
assert(_strings == nullptr, "Must 'clear()' before deleting!");
}
+ void DbgStrings::init(DbgStrings& dbg_strings) {
+ dbg_strings._strings = new DbgStringCollection();
+ }
+
const char* DbgStrings::insert(const char* dbgstr) {
const char* str = _strings->lookup(dbgstr);
return str != nullptr ? str : _strings->insert(dbgstr);
}
clear();
_strings = src._strings->reuse();
}
void DbgStrings::clear() {
+ assert(_strings != nullptr, "sanity check");
if (_strings->clear() == 0) {
delete _strings;
}
_strings = nullptr;
}
< prev index next >