mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
Merge
This commit is contained in:
commit
d6a9b93b5a
133 changed files with 1889 additions and 1307 deletions
|
@ -66,8 +66,6 @@ CodeBlob::CodeBlob(const char* name, int header_size, int size, int frame_comple
|
|||
_relocation_size = locs_size;
|
||||
_instructions_offset = align_code_offset(header_size + locs_size);
|
||||
_data_offset = size;
|
||||
_oops_offset = size;
|
||||
_oops_length = 0;
|
||||
_frame_size = 0;
|
||||
set_oop_maps(NULL);
|
||||
}
|
||||
|
@ -94,9 +92,6 @@ CodeBlob::CodeBlob(
|
|||
_relocation_size = round_to(cb->total_relocation_size(), oopSize);
|
||||
_instructions_offset = align_code_offset(header_size + _relocation_size);
|
||||
_data_offset = _instructions_offset + round_to(cb->total_code_size(), oopSize);
|
||||
_oops_offset = _size - round_to(cb->total_oop_size(), oopSize);
|
||||
_oops_length = 0; // temporary, until the copy_oops handshake
|
||||
assert(_oops_offset >= _data_offset, "codeBlob is too small");
|
||||
assert(_data_offset <= size, "codeBlob is too small");
|
||||
|
||||
cb->copy_code_and_locs_to(this);
|
||||
|
@ -131,99 +126,6 @@ void CodeBlob::flush() {
|
|||
}
|
||||
|
||||
|
||||
// Promote one word from an assembly-time handle to a live embedded oop.
|
||||
inline void CodeBlob::initialize_immediate_oop(oop* dest, jobject handle) {
|
||||
if (handle == NULL ||
|
||||
// As a special case, IC oops are initialized to 1 or -1.
|
||||
handle == (jobject) Universe::non_oop_word()) {
|
||||
(*dest) = (oop)handle;
|
||||
} else {
|
||||
(*dest) = JNIHandles::resolve_non_null(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeBlob::copy_oops(GrowableArray<jobject>* array) {
|
||||
assert(_oops_length == 0, "do this handshake just once, please");
|
||||
int length = array->length();
|
||||
assert((address)(oops_begin() + length) <= data_end(), "oops big enough");
|
||||
oop* dest = oops_begin();
|
||||
for (int index = 0 ; index < length; index++) {
|
||||
initialize_immediate_oop(&dest[index], array->at(index));
|
||||
}
|
||||
_oops_length = length;
|
||||
|
||||
// Now we can fix up all the oops in the code.
|
||||
// We need to do this in the code because
|
||||
// the assembler uses jobjects as placeholders.
|
||||
// The code and relocations have already been
|
||||
// initialized by the CodeBlob constructor,
|
||||
// so it is valid even at this early point to
|
||||
// iterate over relocations and patch the code.
|
||||
fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true);
|
||||
}
|
||||
|
||||
|
||||
relocInfo::relocType CodeBlob::reloc_type_for_address(address pc) {
|
||||
RelocIterator iter(this, pc, pc+1);
|
||||
while (iter.next()) {
|
||||
return (relocInfo::relocType) iter.type();
|
||||
}
|
||||
// No relocation info found for pc
|
||||
ShouldNotReachHere();
|
||||
return relocInfo::none; // dummy return value
|
||||
}
|
||||
|
||||
|
||||
bool CodeBlob::is_at_poll_return(address pc) {
|
||||
RelocIterator iter(this, pc, pc+1);
|
||||
while (iter.next()) {
|
||||
if (iter.type() == relocInfo::poll_return_type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CodeBlob::is_at_poll_or_poll_return(address pc) {
|
||||
RelocIterator iter(this, pc, pc+1);
|
||||
while (iter.next()) {
|
||||
relocInfo::relocType t = iter.type();
|
||||
if (t == relocInfo::poll_return_type || t == relocInfo::poll_type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CodeBlob::fix_oop_relocations(address begin, address end,
|
||||
bool initialize_immediates) {
|
||||
// re-patch all oop-bearing instructions, just in case some oops moved
|
||||
RelocIterator iter(this, begin, end);
|
||||
while (iter.next()) {
|
||||
if (iter.type() == relocInfo::oop_type) {
|
||||
oop_Relocation* reloc = iter.oop_reloc();
|
||||
if (initialize_immediates && reloc->oop_is_immediate()) {
|
||||
oop* dest = reloc->oop_addr();
|
||||
initialize_immediate_oop(dest, (jobject) *dest);
|
||||
}
|
||||
// Refresh the oop-related bits of this instruction.
|
||||
reloc->fix_oop_relocation();
|
||||
}
|
||||
|
||||
// There must not be any interfering patches or breakpoints.
|
||||
assert(!(iter.type() == relocInfo::breakpoint_type
|
||||
&& iter.breakpoint_reloc()->active()),
|
||||
"no active breakpoint");
|
||||
}
|
||||
}
|
||||
|
||||
void CodeBlob::do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
OopMap* CodeBlob::oop_map_for_return_address(address return_address) {
|
||||
address pc = return_address ;
|
||||
assert (oop_maps() != NULL, "nope");
|
||||
|
|
|
@ -54,17 +54,12 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
|||
// that range. There is a similar range(s) on returns
|
||||
// which we don't detect.
|
||||
int _data_offset; // offset to where data region begins
|
||||
int _oops_offset; // offset to where embedded oop table begins (inside data)
|
||||
int _oops_length; // number of embedded oops
|
||||
int _frame_size; // size of stack frame
|
||||
OopMapSet* _oop_maps; // OopMap for this CodeBlob
|
||||
CodeComments _comments;
|
||||
|
||||
friend class OopRecorder;
|
||||
|
||||
void fix_oop_relocations(address begin, address end, bool initialize_immediates);
|
||||
inline void initialize_immediate_oop(oop* dest, jobject handle);
|
||||
|
||||
public:
|
||||
// Returns the space needed for CodeBlob
|
||||
static unsigned int allocation_size(CodeBuffer* cb, int header_size);
|
||||
|
@ -115,14 +110,11 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
|||
address instructions_end() const { return (address) header_begin() + _data_offset; }
|
||||
address data_begin() const { return (address) header_begin() + _data_offset; }
|
||||
address data_end() const { return (address) header_begin() + _size; }
|
||||
oop* oops_begin() const { return (oop*) (header_begin() + _oops_offset); }
|
||||
oop* oops_end() const { return oops_begin() + _oops_length; }
|
||||
|
||||
// Offsets
|
||||
int relocation_offset() const { return _header_size; }
|
||||
int instructions_offset() const { return _instructions_offset; }
|
||||
int data_offset() const { return _data_offset; }
|
||||
int oops_offset() const { return _oops_offset; }
|
||||
|
||||
// Sizes
|
||||
int size() const { return _size; }
|
||||
|
@ -130,40 +122,16 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
|||
int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }
|
||||
int instructions_size() const { return instructions_end() - instructions_begin(); }
|
||||
int data_size() const { return data_end() - data_begin(); }
|
||||
int oops_size() const { return (address) oops_end() - (address) oops_begin(); }
|
||||
|
||||
// Containment
|
||||
bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }
|
||||
bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); }
|
||||
bool instructions_contains(address addr) const { return instructions_begin() <= addr && addr < instructions_end(); }
|
||||
bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); }
|
||||
bool oops_contains(oop* addr) const { return oops_begin() <= addr && addr < oops_end(); }
|
||||
bool contains(address addr) const { return instructions_contains(addr); }
|
||||
bool is_frame_complete_at(address addr) const { return instructions_contains(addr) &&
|
||||
addr >= instructions_begin() + _frame_complete_offset; }
|
||||
|
||||
// Relocation support
|
||||
void fix_oop_relocations(address begin, address end) {
|
||||
fix_oop_relocations(begin, end, false);
|
||||
}
|
||||
void fix_oop_relocations() {
|
||||
fix_oop_relocations(NULL, NULL, false);
|
||||
}
|
||||
relocInfo::relocType reloc_type_for_address(address pc);
|
||||
bool is_at_poll_return(address pc);
|
||||
bool is_at_poll_or_poll_return(address pc);
|
||||
|
||||
// Support for oops in scopes and relocs:
|
||||
// Note: index 0 is reserved for null.
|
||||
oop oop_at(int index) const { return index == 0? (oop)NULL: *oop_addr_at(index); }
|
||||
oop* oop_addr_at(int index) const{ // for GC
|
||||
// relocation indexes are biased by 1 (because 0 is reserved)
|
||||
assert(index > 0 && index <= _oops_length, "must be a valid non-zero index");
|
||||
return &oops_begin()[index-1];
|
||||
}
|
||||
|
||||
void copy_oops(GrowableArray<jobject>* oops);
|
||||
|
||||
// CodeCache support: really only used by the nmethods, but in order to get
|
||||
// asserts and certain bookkeeping to work in the CodeCache they are defined
|
||||
// virtual here.
|
||||
|
@ -175,12 +143,6 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
|||
|
||||
// GC support
|
||||
virtual bool is_alive() const = 0;
|
||||
virtual void do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred);
|
||||
virtual void oops_do(OopClosure* f) = 0;
|
||||
// (All CodeBlob subtypes other than NMethod currently have
|
||||
// an empty oops_do() method.
|
||||
|
||||
// OopMap for frame
|
||||
OopMapSet* oop_maps() const { return _oop_maps; }
|
||||
|
@ -245,11 +207,6 @@ class BufferBlob: public CodeBlob {
|
|||
// GC/Verification support
|
||||
void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
|
||||
bool is_alive() const { return true; }
|
||||
void do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred) { /* do nothing */ }
|
||||
|
||||
void oops_do(OopClosure* f) { /* do nothing*/ }
|
||||
|
||||
void verify();
|
||||
void print() const PRODUCT_RETURN;
|
||||
|
@ -334,10 +291,6 @@ class RuntimeStub: public CodeBlob {
|
|||
// GC/Verification support
|
||||
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
|
||||
bool is_alive() const { return true; }
|
||||
void do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred) { /* do nothing */ }
|
||||
void oops_do(OopClosure* f) { /* do-nothing*/ }
|
||||
|
||||
void verify();
|
||||
void print() const PRODUCT_RETURN;
|
||||
|
@ -363,9 +316,6 @@ class SingletonBlob: public CodeBlob {
|
|||
{};
|
||||
|
||||
bool is_alive() const { return true; }
|
||||
void do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred) { /* do-nothing*/ }
|
||||
|
||||
void verify(); // does nothing
|
||||
void print() const PRODUCT_RETURN;
|
||||
|
@ -423,9 +373,6 @@ class DeoptimizationBlob: public SingletonBlob {
|
|||
// GC for args
|
||||
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ }
|
||||
|
||||
// Iteration
|
||||
void oops_do(OopClosure* f) {}
|
||||
|
||||
// Printing
|
||||
void print_value_on(outputStream* st) const PRODUCT_RETURN;
|
||||
|
||||
|
@ -477,9 +424,6 @@ class UncommonTrapBlob: public SingletonBlob {
|
|||
|
||||
// Typing
|
||||
bool is_uncommon_trap_stub() const { return true; }
|
||||
|
||||
// Iteration
|
||||
void oops_do(OopClosure* f) {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -512,9 +456,6 @@ class ExceptionBlob: public SingletonBlob {
|
|||
|
||||
// Typing
|
||||
bool is_exception_stub() const { return true; }
|
||||
|
||||
// Iteration
|
||||
void oops_do(OopClosure* f) {}
|
||||
};
|
||||
#endif // COMPILER2
|
||||
|
||||
|
@ -548,7 +489,4 @@ class SafepointBlob: public SingletonBlob {
|
|||
|
||||
// Typing
|
||||
bool is_safepoint_stub() const { return true; }
|
||||
|
||||
// Iteration
|
||||
void oops_do(OopClosure* f) {}
|
||||
};
|
||||
|
|
|
@ -74,12 +74,12 @@ class CodeBlob_sizes {
|
|||
total_size += cb->size();
|
||||
header_size += cb->header_size();
|
||||
relocation_size += cb->relocation_size();
|
||||
scopes_oop_size += cb->oops_size();
|
||||
if (cb->is_nmethod()) {
|
||||
nmethod *nm = (nmethod*)cb;
|
||||
nmethod* nm = cb->as_nmethod_or_null();
|
||||
code_size += nm->code_size();
|
||||
stub_size += nm->stub_size();
|
||||
|
||||
scopes_oop_size += nm->oops_size();
|
||||
scopes_data_size += nm->scopes_data_size();
|
||||
scopes_pcs_size += nm->scopes_pcs_size();
|
||||
} else {
|
||||
|
@ -262,14 +262,14 @@ int CodeCache::alignment_offset() {
|
|||
}
|
||||
|
||||
|
||||
// Mark code blobs for unloading if they contain otherwise
|
||||
// unreachable oops.
|
||||
// Mark nmethods for unloading if they contain otherwise unreachable
|
||||
// oops.
|
||||
void CodeCache::do_unloading(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
bool unloading_occurred) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
FOR_ALL_ALIVE_BLOBS(cb) {
|
||||
cb->do_unloading(is_alive, keep_alive, unloading_occurred);
|
||||
FOR_ALL_ALIVE_NMETHODS(nm) {
|
||||
nm->do_unloading(is_alive, keep_alive, unloading_occurred);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,9 +509,9 @@ void CodeCache::gc_epilogue() {
|
|||
if (needs_cache_clean()) {
|
||||
nm->cleanup_inline_caches();
|
||||
}
|
||||
debug_only(nm->verify();)
|
||||
DEBUG_ONLY(nm->verify());
|
||||
nm->fix_oop_relocations();
|
||||
}
|
||||
cb->fix_oop_relocations();
|
||||
}
|
||||
set_needs_cache_clean(false);
|
||||
prune_scavenge_root_nmethods();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -441,11 +441,11 @@ void CompiledIC::compute_monomorphic_entry(methodHandle method,
|
|||
}
|
||||
|
||||
|
||||
inline static RelocIterator parse_ic(CodeBlob* code, address ic_call, oop* &_oop_addr, bool *is_optimized) {
|
||||
inline static RelocIterator parse_ic(nmethod* nm, address ic_call, oop* &_oop_addr, bool *is_optimized) {
|
||||
address first_oop = NULL;
|
||||
// Mergers please note: Sun SC5.x CC insists on an lvalue for a reference parameter.
|
||||
CodeBlob *code1 = code;
|
||||
return virtual_call_Relocation::parse_ic(code1, ic_call, first_oop, _oop_addr, is_optimized);
|
||||
nmethod* tmp_nm = nm;
|
||||
return virtual_call_Relocation::parse_ic(tmp_nm, ic_call, first_oop, _oop_addr, is_optimized);
|
||||
}
|
||||
|
||||
CompiledIC::CompiledIC(NativeCall* ic_call)
|
||||
|
|
|
@ -99,12 +99,12 @@ struct nmethod_stats_struct {
|
|||
code_size += nm->code_size();
|
||||
stub_size += nm->stub_size();
|
||||
consts_size += nm->consts_size();
|
||||
oops_size += nm->oops_size();
|
||||
scopes_data_size += nm->scopes_data_size();
|
||||
scopes_pcs_size += nm->scopes_pcs_size();
|
||||
dependencies_size += nm->dependencies_size();
|
||||
handler_table_size += nm->handler_table_size();
|
||||
nul_chk_table_size += nm->nul_chk_table_size();
|
||||
oops_size += nm->oops_size();
|
||||
}
|
||||
void print_nmethod_stats() {
|
||||
if (nmethod_count == 0) return;
|
||||
|
@ -114,12 +114,12 @@ struct nmethod_stats_struct {
|
|||
if (code_size != 0) tty->print_cr(" main code = %d", code_size);
|
||||
if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size);
|
||||
if (consts_size != 0) tty->print_cr(" constants = %d", consts_size);
|
||||
if (oops_size != 0) tty->print_cr(" oops = %d", oops_size);
|
||||
if (scopes_data_size != 0) tty->print_cr(" scopes data = %d", scopes_data_size);
|
||||
if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size);
|
||||
if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size);
|
||||
if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size);
|
||||
if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size);
|
||||
if (oops_size != 0) tty->print_cr(" oops = %d", oops_size);
|
||||
}
|
||||
|
||||
int native_nmethod_count;
|
||||
|
@ -600,7 +600,8 @@ nmethod::nmethod(
|
|||
#endif // def HAVE_DTRACE_H
|
||||
_stub_offset = data_offset();
|
||||
_consts_offset = data_offset();
|
||||
_scopes_data_offset = data_offset();
|
||||
_oops_offset = data_offset();
|
||||
_scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize);
|
||||
_scopes_pcs_offset = _scopes_data_offset;
|
||||
_dependencies_offset = _scopes_pcs_offset;
|
||||
_handler_table_offset = _dependencies_offset;
|
||||
|
@ -690,7 +691,8 @@ nmethod::nmethod(
|
|||
_orig_pc_offset = 0;
|
||||
_stub_offset = data_offset();
|
||||
_consts_offset = data_offset();
|
||||
_scopes_data_offset = data_offset();
|
||||
_oops_offset = data_offset();
|
||||
_scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize);
|
||||
_scopes_pcs_offset = _scopes_data_offset;
|
||||
_dependencies_offset = _scopes_pcs_offset;
|
||||
_handler_table_offset = _dependencies_offset;
|
||||
|
@ -805,8 +807,9 @@ nmethod::nmethod(
|
|||
_unwind_handler_offset = -1;
|
||||
}
|
||||
_consts_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start());
|
||||
_scopes_data_offset = data_offset();
|
||||
_scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize);
|
||||
_oops_offset = data_offset();
|
||||
_scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size (), oopSize);
|
||||
_scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize);
|
||||
_dependencies_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size());
|
||||
_handler_table_offset = _dependencies_offset + round_to(dependencies->size_in_bytes (), oopSize);
|
||||
_nul_chk_table_offset = _handler_table_offset + round_to(handler_table->size_in_bytes(), oopSize);
|
||||
|
@ -990,6 +993,79 @@ void nmethod::set_version(int v) {
|
|||
}
|
||||
|
||||
|
||||
// Promote one word from an assembly-time handle to a live embedded oop.
|
||||
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
|
||||
if (handle == NULL ||
|
||||
// As a special case, IC oops are initialized to 1 or -1.
|
||||
handle == (jobject) Universe::non_oop_word()) {
|
||||
(*dest) = (oop) handle;
|
||||
} else {
|
||||
(*dest) = JNIHandles::resolve_non_null(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nmethod::copy_oops(GrowableArray<jobject>* array) {
|
||||
//assert(oops_size() == 0, "do this handshake just once, please");
|
||||
int length = array->length();
|
||||
assert((address)(oops_begin() + length) <= data_end(), "oops big enough");
|
||||
oop* dest = oops_begin();
|
||||
for (int index = 0 ; index < length; index++) {
|
||||
initialize_immediate_oop(&dest[index], array->at(index));
|
||||
}
|
||||
|
||||
// Now we can fix up all the oops in the code. We need to do this
|
||||
// in the code because the assembler uses jobjects as placeholders.
|
||||
// The code and relocations have already been initialized by the
|
||||
// CodeBlob constructor, so it is valid even at this early point to
|
||||
// iterate over relocations and patch the code.
|
||||
fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true);
|
||||
}
|
||||
|
||||
|
||||
bool nmethod::is_at_poll_return(address pc) {
|
||||
RelocIterator iter(this, pc, pc+1);
|
||||
while (iter.next()) {
|
||||
if (iter.type() == relocInfo::poll_return_type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool nmethod::is_at_poll_or_poll_return(address pc) {
|
||||
RelocIterator iter(this, pc, pc+1);
|
||||
while (iter.next()) {
|
||||
relocInfo::relocType t = iter.type();
|
||||
if (t == relocInfo::poll_return_type || t == relocInfo::poll_type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) {
|
||||
// re-patch all oop-bearing instructions, just in case some oops moved
|
||||
RelocIterator iter(this, begin, end);
|
||||
while (iter.next()) {
|
||||
if (iter.type() == relocInfo::oop_type) {
|
||||
oop_Relocation* reloc = iter.oop_reloc();
|
||||
if (initialize_immediates && reloc->oop_is_immediate()) {
|
||||
oop* dest = reloc->oop_addr();
|
||||
initialize_immediate_oop(dest, (jobject) *dest);
|
||||
}
|
||||
// Refresh the oop-related bits of this instruction.
|
||||
reloc->fix_oop_relocation();
|
||||
}
|
||||
|
||||
// There must not be any interfering patches or breakpoints.
|
||||
assert(!(iter.type() == relocInfo::breakpoint_type
|
||||
&& iter.breakpoint_reloc()->active()),
|
||||
"no active breakpoint");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScopeDesc* nmethod::scope_desc_at(address pc) {
|
||||
PcDesc* pd = pc_desc_at(pc);
|
||||
guarantee(pd != NULL, "scope must be present");
|
||||
|
@ -1266,19 +1342,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||
// and it hasn't already been reported for this nmethod then report it now.
|
||||
// (the event may have been reported earilier if the GC marked it for unloading).
|
||||
if (state == zombie) {
|
||||
|
||||
DTRACE_METHOD_UNLOAD_PROBE(method());
|
||||
|
||||
if (JvmtiExport::should_post_compiled_method_unload() &&
|
||||
!unload_reported()) {
|
||||
assert(method() != NULL, "checking");
|
||||
{
|
||||
HandleMark hm;
|
||||
JvmtiExport::post_compiled_method_unload_at_safepoint(
|
||||
method()->jmethod_id(), code_begin());
|
||||
}
|
||||
set_unload_reported();
|
||||
}
|
||||
post_compiled_method_unload();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1430,6 +1494,12 @@ void nmethod::post_compiled_method_load_event() {
|
|||
}
|
||||
|
||||
void nmethod::post_compiled_method_unload() {
|
||||
if (unload_reported()) {
|
||||
// During unloading we transition to unloaded and then to zombie
|
||||
// and the unloading is reported during the first transition.
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_method != NULL && !is_unloaded(), "just checking");
|
||||
DTRACE_METHOD_UNLOAD_PROBE(method());
|
||||
|
||||
|
@ -1439,8 +1509,7 @@ void nmethod::post_compiled_method_unload() {
|
|||
if (JvmtiExport::should_post_compiled_method_unload()) {
|
||||
assert(!unload_reported(), "already unloaded");
|
||||
HandleMark hm;
|
||||
JvmtiExport::post_compiled_method_unload_at_safepoint(
|
||||
method()->jmethod_id(), code_begin());
|
||||
JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
|
||||
}
|
||||
|
||||
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
|
||||
|
@ -2282,6 +2351,10 @@ void nmethod::print() const {
|
|||
consts_begin(),
|
||||
consts_end(),
|
||||
consts_size());
|
||||
if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
|
||||
oops_begin(),
|
||||
oops_end(),
|
||||
oops_size());
|
||||
if (scopes_data_size () > 0) tty->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
|
||||
scopes_data_begin(),
|
||||
scopes_data_end(),
|
||||
|
|
|
@ -105,6 +105,7 @@ struct nmFlags {
|
|||
// [Relocation]
|
||||
// - relocation information
|
||||
// - constant part (doubles, longs and floats used in nmethod)
|
||||
// - oop table
|
||||
// [Code]
|
||||
// - code body
|
||||
// - exception handler
|
||||
|
@ -161,6 +162,7 @@ class nmethod : public CodeBlob {
|
|||
#endif // def HAVE_DTRACE_H
|
||||
int _stub_offset;
|
||||
int _consts_offset;
|
||||
int _oops_offset; // offset to where embedded oop table begins (inside data)
|
||||
int _scopes_data_offset;
|
||||
int _scopes_pcs_offset;
|
||||
int _dependencies_offset;
|
||||
|
@ -347,7 +349,10 @@ class nmethod : public CodeBlob {
|
|||
address stub_begin () const { return header_begin() + _stub_offset ; }
|
||||
address stub_end () const { return header_begin() + _consts_offset ; }
|
||||
address consts_begin () const { return header_begin() + _consts_offset ; }
|
||||
address consts_end () const { return header_begin() + _scopes_data_offset ; }
|
||||
address consts_end () const { return header_begin() + _oops_offset ; }
|
||||
oop* oops_begin () const { return (oop*) (header_begin() + _oops_offset) ; }
|
||||
oop* oops_end () const { return (oop*) (header_begin() + _scopes_data_offset) ; }
|
||||
|
||||
address scopes_data_begin () const { return header_begin() + _scopes_data_offset ; }
|
||||
address scopes_data_end () const { return header_begin() + _scopes_pcs_offset ; }
|
||||
PcDesc* scopes_pcs_begin () const { return (PcDesc*)(header_begin() + _scopes_pcs_offset ); }
|
||||
|
@ -359,20 +364,24 @@ class nmethod : public CodeBlob {
|
|||
address nul_chk_table_begin () const { return header_begin() + _nul_chk_table_offset ; }
|
||||
address nul_chk_table_end () const { return header_begin() + _nmethod_end_offset ; }
|
||||
|
||||
int code_size () const { return code_end () - code_begin (); }
|
||||
int stub_size () const { return stub_end () - stub_begin (); }
|
||||
int consts_size () const { return consts_end () - consts_begin (); }
|
||||
int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); }
|
||||
int scopes_pcs_size () const { return (intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin (); }
|
||||
int dependencies_size () const { return dependencies_end () - dependencies_begin (); }
|
||||
int handler_table_size() const { return handler_table_end() - handler_table_begin(); }
|
||||
int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }
|
||||
// Sizes
|
||||
int code_size () const { return code_end () - code_begin (); }
|
||||
int stub_size () const { return stub_end () - stub_begin (); }
|
||||
int consts_size () const { return consts_end () - consts_begin (); }
|
||||
int oops_size () const { return (address) oops_end () - (address) oops_begin (); }
|
||||
int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); }
|
||||
int scopes_pcs_size () const { return (intptr_t) scopes_pcs_end () - (intptr_t) scopes_pcs_begin (); }
|
||||
int dependencies_size () const { return dependencies_end () - dependencies_begin (); }
|
||||
int handler_table_size() const { return handler_table_end() - handler_table_begin(); }
|
||||
int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }
|
||||
|
||||
int total_size () const;
|
||||
|
||||
// Containment
|
||||
bool code_contains (address addr) const { return code_begin () <= addr && addr < code_end (); }
|
||||
bool stub_contains (address addr) const { return stub_begin () <= addr && addr < stub_end (); }
|
||||
bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); }
|
||||
bool oops_contains (oop* addr) const { return oops_begin () <= addr && addr < oops_end (); }
|
||||
bool scopes_data_contains (address addr) const { return scopes_data_begin () <= addr && addr < scopes_data_end (); }
|
||||
bool scopes_pcs_contains (PcDesc* addr) const { return scopes_pcs_begin () <= addr && addr < scopes_pcs_end (); }
|
||||
bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); }
|
||||
|
@ -431,6 +440,29 @@ class nmethod : public CodeBlob {
|
|||
int version() const { return flags.version; }
|
||||
void set_version(int v);
|
||||
|
||||
// Support for oops in scopes and relocs:
|
||||
// Note: index 0 is reserved for null.
|
||||
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
|
||||
oop* oop_addr_at(int index) const { // for GC
|
||||
// relocation indexes are biased by 1 (because 0 is reserved)
|
||||
assert(index > 0 && index <= oops_size(), "must be a valid non-zero index");
|
||||
return &oops_begin()[index - 1];
|
||||
}
|
||||
|
||||
void copy_oops(GrowableArray<jobject>* oops);
|
||||
|
||||
// Relocation support
|
||||
private:
|
||||
void fix_oop_relocations(address begin, address end, bool initialize_immediates);
|
||||
inline void initialize_immediate_oop(oop* dest, jobject handle);
|
||||
|
||||
public:
|
||||
void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); }
|
||||
void fix_oop_relocations() { fix_oop_relocations(NULL, NULL, false); }
|
||||
|
||||
bool is_at_poll_return(address pc);
|
||||
bool is_at_poll_or_poll_return(address pc);
|
||||
|
||||
// Non-perm oop support
|
||||
bool on_scavenge_root_list() const { return (_scavenge_root_state & 1) != 0; }
|
||||
protected:
|
||||
|
@ -511,8 +543,8 @@ class nmethod : public CodeBlob {
|
|||
|
||||
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
|
||||
OopClosure* f);
|
||||
virtual void oops_do(OopClosure* f) { oops_do(f, false); }
|
||||
void oops_do(OopClosure* f, bool do_strong_roots_only);
|
||||
void oops_do(OopClosure* f) { oops_do(f, false); }
|
||||
void oops_do(OopClosure* f, bool do_strong_roots_only);
|
||||
bool detect_scavenge_root_oops();
|
||||
void verify_scavenge_root_oops() PRODUCT_RETURN;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -50,10 +50,10 @@ int OopRecorder::oop_size() {
|
|||
return _handles->length() * sizeof(oop);
|
||||
}
|
||||
|
||||
void OopRecorder::copy_to(CodeBlob* code) {
|
||||
void OopRecorder::copy_to(nmethod* nm) {
|
||||
assert(_complete, "must be frozen");
|
||||
maybe_initialize(); // get non-null handles, even if we have no oops
|
||||
code->copy_oops(_handles);
|
||||
nm->copy_oops(_handles);
|
||||
}
|
||||
|
||||
void OopRecorder::maybe_initialize() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -70,8 +70,8 @@ class OopRecorder : public ResourceObj {
|
|||
return _handles->length() + first_index;
|
||||
}
|
||||
|
||||
// copy the generated oop table to CodeBlob
|
||||
void copy_to(CodeBlob* code); // => code->copy_oops(_handles)
|
||||
// copy the generated oop table to nmethod
|
||||
void copy_to(nmethod* nm); // => nm->copy_oops(_handles)
|
||||
|
||||
bool is_unused() { return _handles == NULL && !_complete; }
|
||||
#ifdef ASSERT
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -115,24 +115,25 @@ void relocInfo::remove_reloc_info_for_address(RelocIterator *itr, address pc, re
|
|||
// ----------------------------------------------------------------------------------------------------
|
||||
// Implementation of RelocIterator
|
||||
|
||||
void RelocIterator::initialize(CodeBlob* cb, address begin, address limit) {
|
||||
void RelocIterator::initialize(nmethod* nm, address begin, address limit) {
|
||||
initialize_misc();
|
||||
|
||||
if (cb == NULL && begin != NULL) {
|
||||
// allow CodeBlob to be deduced from beginning address
|
||||
cb = CodeCache::find_blob(begin);
|
||||
if (nm == NULL && begin != NULL) {
|
||||
// allow nmethod to be deduced from beginning address
|
||||
CodeBlob* cb = CodeCache::find_blob(begin);
|
||||
nm = cb->as_nmethod_or_null();
|
||||
}
|
||||
assert(cb != NULL, "must be able to deduce nmethod from other arguments");
|
||||
assert(nm != NULL, "must be able to deduce nmethod from other arguments");
|
||||
|
||||
_code = cb;
|
||||
_current = cb->relocation_begin()-1;
|
||||
_end = cb->relocation_end();
|
||||
_addr = (address) cb->instructions_begin();
|
||||
_code = nm;
|
||||
_current = nm->relocation_begin() - 1;
|
||||
_end = nm->relocation_end();
|
||||
_addr = (address) nm->instructions_begin();
|
||||
|
||||
assert(!has_current(), "just checking");
|
||||
address code_end = cb->instructions_end();
|
||||
address code_end = nm->instructions_end();
|
||||
|
||||
assert(begin == NULL || begin >= cb->instructions_begin(), "in bounds");
|
||||
assert(begin == NULL || begin >= nm->instructions_begin(), "in bounds");
|
||||
// FIX THIS assert(limit == NULL || limit <= code_end, "in bounds");
|
||||
set_limits(begin, limit);
|
||||
}
|
||||
|
@ -754,7 +755,7 @@ oop* oop_Relocation::oop_addr() {
|
|||
// oop is stored in the code stream
|
||||
return (oop*) pd_address_in_code();
|
||||
} else {
|
||||
// oop is stored in table at CodeBlob::oops_begin
|
||||
// oop is stored in table at nmethod::oops_begin
|
||||
return code()->oop_addr_at(n);
|
||||
}
|
||||
}
|
||||
|
@ -776,26 +777,28 @@ void oop_Relocation::fix_oop_relocation() {
|
|||
}
|
||||
|
||||
|
||||
RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_call, address &first_oop,
|
||||
RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop,
|
||||
oop* &oop_addr, bool *is_optimized) {
|
||||
assert(ic_call != NULL, "ic_call address must be set");
|
||||
assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input");
|
||||
if (code == NULL) {
|
||||
if (nm == NULL) {
|
||||
CodeBlob* code;
|
||||
if (ic_call != NULL) {
|
||||
code = CodeCache::find_blob(ic_call);
|
||||
} else if (first_oop != NULL) {
|
||||
code = CodeCache::find_blob(first_oop);
|
||||
}
|
||||
assert(code != NULL, "address to parse must be in CodeBlob");
|
||||
nm = code->as_nmethod_or_null();
|
||||
assert(nm != NULL, "address to parse must be in nmethod");
|
||||
}
|
||||
assert(ic_call == NULL || code->contains(ic_call), "must be in CodeBlob");
|
||||
assert(first_oop == NULL || code->contains(first_oop), "must be in CodeBlob");
|
||||
assert(ic_call == NULL || nm->contains(ic_call), "must be in nmethod");
|
||||
assert(first_oop == NULL || nm->contains(first_oop), "must be in nmethod");
|
||||
|
||||
address oop_limit = NULL;
|
||||
|
||||
if (ic_call != NULL) {
|
||||
// search for the ic_call at the given address
|
||||
RelocIterator iter(code, ic_call, ic_call+1);
|
||||
RelocIterator iter(nm, ic_call, ic_call+1);
|
||||
bool ret = iter.next();
|
||||
assert(ret == true, "relocInfo must exist at this address");
|
||||
assert(iter.addr() == ic_call, "must find ic_call");
|
||||
|
@ -814,7 +817,7 @@ RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_cal
|
|||
}
|
||||
|
||||
// search for the first_oop, to get its oop_addr
|
||||
RelocIterator all_oops(code, first_oop);
|
||||
RelocIterator all_oops(nm, first_oop);
|
||||
RelocIterator iter = all_oops;
|
||||
iter.set_limit(first_oop+1);
|
||||
bool found_oop = false;
|
||||
|
@ -842,7 +845,7 @@ RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_cal
|
|||
}
|
||||
}
|
||||
guarantee(!did_reset, "cannot find ic_call");
|
||||
iter = RelocIterator(code); // search the whole CodeBlob
|
||||
iter = RelocIterator(nm); // search the whole nmethod
|
||||
did_reset = true;
|
||||
}
|
||||
|
||||
|
@ -1175,9 +1178,9 @@ void RelocIterator::print() {
|
|||
|
||||
// For the debugger:
|
||||
extern "C"
|
||||
void print_blob_locs(CodeBlob* cb) {
|
||||
cb->print();
|
||||
RelocIterator iter(cb);
|
||||
void print_blob_locs(nmethod* nm) {
|
||||
nm->print();
|
||||
RelocIterator iter(nm);
|
||||
iter.print();
|
||||
}
|
||||
extern "C"
|
||||
|
|
|
@ -512,7 +512,7 @@ class RelocIterator : public StackObj {
|
|||
address _limit; // stop producing relocations after this _addr
|
||||
relocInfo* _current; // the current relocation information
|
||||
relocInfo* _end; // end marker; we're done iterating when _current == _end
|
||||
CodeBlob* _code; // compiled method containing _addr
|
||||
nmethod* _code; // compiled method containing _addr
|
||||
address _addr; // instruction to which the relocation applies
|
||||
short _databuf; // spare buffer for compressed data
|
||||
short* _data; // pointer to the relocation's data
|
||||
|
@ -549,7 +549,7 @@ class RelocIterator : public StackObj {
|
|||
|
||||
address compute_section_start(int n) const; // out-of-line helper
|
||||
|
||||
void initialize(CodeBlob* nm, address begin, address limit);
|
||||
void initialize(nmethod* nm, address begin, address limit);
|
||||
|
||||
friend class PatchingRelocIterator;
|
||||
// make an uninitialized one, for PatchingRelocIterator:
|
||||
|
@ -557,7 +557,7 @@ class RelocIterator : public StackObj {
|
|||
|
||||
public:
|
||||
// constructor
|
||||
RelocIterator(CodeBlob* cb, address begin = NULL, address limit = NULL);
|
||||
RelocIterator(nmethod* nm, address begin = NULL, address limit = NULL);
|
||||
RelocIterator(CodeSection* cb, address begin = NULL, address limit = NULL);
|
||||
|
||||
// get next reloc info, return !eos
|
||||
|
@ -592,7 +592,7 @@ class RelocIterator : public StackObj {
|
|||
relocType type() const { return current()->type(); }
|
||||
int format() const { return (relocInfo::have_format) ? current()->format() : 0; }
|
||||
address addr() const { return _addr; }
|
||||
CodeBlob* code() const { return _code; }
|
||||
nmethod* code() const { return _code; }
|
||||
short* data() const { return _data; }
|
||||
int datalen() const { return _datalen; }
|
||||
bool has_current() const { return _datalen >= 0; }
|
||||
|
@ -790,9 +790,9 @@ class Relocation VALUE_OBJ_CLASS_SPEC {
|
|||
|
||||
public:
|
||||
// accessors which only make sense for a bound Relocation
|
||||
address addr() const { return binding()->addr(); }
|
||||
CodeBlob* code() const { return binding()->code(); }
|
||||
bool addr_in_const() const { return binding()->addr_in_const(); }
|
||||
address addr() const { return binding()->addr(); }
|
||||
nmethod* code() const { return binding()->code(); }
|
||||
bool addr_in_const() const { return binding()->addr_in_const(); }
|
||||
protected:
|
||||
short* data() const { return binding()->data(); }
|
||||
int datalen() const { return binding()->datalen(); }
|
||||
|
@ -982,12 +982,12 @@ class virtual_call_Relocation : public CallRelocation {
|
|||
|
||||
// Figure out where an ic_call is hiding, given a set-oop or call.
|
||||
// Either ic_call or first_oop must be non-null; the other is deduced.
|
||||
// Code if non-NULL must be the CodeBlob, else it is deduced.
|
||||
// Code if non-NULL must be the nmethod, else it is deduced.
|
||||
// The address of the patchable oop is also deduced.
|
||||
// The returned iterator will enumerate over the oops and the ic_call,
|
||||
// as well as any other relocations that happen to be in that span of code.
|
||||
// Recognize relevant set_oops with: oop_reloc()->oop_addr() == oop_addr.
|
||||
static RelocIterator parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized);
|
||||
static RelocIterator parse_ic(nmethod* &nm, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1304,8 +1304,8 @@ inline name##_Relocation* RelocIterator::name##_reloc() { \
|
|||
APPLY_TO_RELOCATIONS(EACH_CASE);
|
||||
#undef EACH_CASE
|
||||
|
||||
inline RelocIterator::RelocIterator(CodeBlob* cb, address begin, address limit) {
|
||||
initialize(cb, begin, limit);
|
||||
inline RelocIterator::RelocIterator(nmethod* nm, address begin, address limit) {
|
||||
initialize(nm, begin, limit);
|
||||
}
|
||||
|
||||
// if you are going to patch code, you should use this subclass of
|
||||
|
@ -1323,8 +1323,8 @@ class PatchingRelocIterator : public RelocIterator {
|
|||
void operator=(const RelocIterator&);
|
||||
|
||||
public:
|
||||
PatchingRelocIterator(CodeBlob* cb, address begin =NULL, address limit =NULL)
|
||||
: RelocIterator(cb, begin, limit) { prepass(); }
|
||||
PatchingRelocIterator(nmethod* nm, address begin = NULL, address limit = NULL)
|
||||
: RelocIterator(nm, begin, limit) { prepass(); }
|
||||
|
||||
~PatchingRelocIterator() { postpass(); }
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue