提交 9ae3a3cd 编写于 作者: N never

6911204: generated adapters with large signatures can fill up the code cache

Reviewed-by: kvn, jrose
上级 0b9139fb
/*
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, Inc. 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
......@@ -1189,7 +1189,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
// VMReg max_arg,
int comp_args_on_stack, // VMRegStackSlots
const BasicType *sig_bt,
const VMRegPair *regs) {
const VMRegPair *regs,
AdapterFingerPrint* fingerprint) {
address i2c_entry = __ pc();
AdapterGenerator agen(masm);
......@@ -1258,7 +1259,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
__ flush();
return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry);
return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
}
......
/*
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, Inc. 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
......@@ -907,7 +907,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
int total_args_passed,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs) {
const VMRegPair *regs,
AdapterFingerPrint* fingerprint) {
address i2c_entry = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
......@@ -954,7 +955,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
__ flush();
return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry);
return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
}
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
......
/*
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, Inc. 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
......@@ -778,7 +778,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
int total_args_passed,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs) {
const VMRegPair *regs,
AdapterFingerPrint* fingerprint) {
address i2c_entry = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
......@@ -824,7 +825,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
__ flush();
return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry);
return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
}
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
......
......@@ -921,6 +921,7 @@ classFileStream.hpp top.hpp
classLoader.cpp allocation.inline.hpp
classLoader.cpp arguments.hpp
classLoader.cpp bytecodeStream.hpp
classLoader.cpp classFileParser.hpp
classLoader.cpp classFileStream.hpp
classLoader.cpp classLoader.hpp
......@@ -948,6 +949,7 @@ classLoader.cpp jvm_misc.hpp
classLoader.cpp management.hpp
classLoader.cpp oop.inline.hpp
classLoader.cpp oopFactory.hpp
classLoader.cpp oopMapCache.hpp
classLoader.cpp os_<os_family>.inline.hpp
classLoader.cpp symbolOop.hpp
classLoader.cpp systemDictionary.hpp
......@@ -3724,6 +3726,7 @@ sharedRuntime.cpp events.hpp
sharedRuntime.cpp forte.hpp
sharedRuntime.cpp gcLocker.inline.hpp
sharedRuntime.cpp handles.inline.hpp
sharedRuntime.cpp hashtable.inline.hpp
sharedRuntime.cpp init.hpp
sharedRuntime.cpp interfaceSupport.hpp
sharedRuntime.cpp interpreterRuntime.hpp
......@@ -3751,6 +3754,7 @@ sharedRuntime.cpp xmlstream.hpp
sharedRuntime.hpp allocation.hpp
sharedRuntime.hpp bytecodeHistogram.hpp
sharedRuntime.hpp bytecodeTracer.hpp
sharedRuntime.hpp hashtable.hpp
sharedRuntime.hpp linkResolver.hpp
sharedRuntime.hpp resourceArea.hpp
sharedRuntime.hpp threadLocalStorage.hpp
......
......@@ -688,7 +688,7 @@ address methodOopDesc::make_adapters(methodHandle mh, TRAPS) {
// so making them eagerly shouldn't be too expensive.
AdapterHandlerEntry* adapter = AdapterHandlerLibrary::get_adapter(mh);
if (adapter == NULL ) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "out of space in CodeCache for adapters");
}
mh->set_adapter_entry(adapter);
......
/*
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2010 Sun Microsystems, Inc. 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
......@@ -1680,6 +1680,8 @@ void SharedRuntime::print_statistics() {
if( _find_handler_ctr ) tty->print_cr("%5d find exception handler", _find_handler_ctr );
if( _rethrow_ctr ) tty->print_cr("%5d rethrow handler", _rethrow_ctr );
AdapterHandlerLibrary::print_statistics();
if (xtty != NULL) xtty->tail("statistics");
}
......@@ -1780,11 +1782,258 @@ void SharedRuntime::print_call_statistics(int comp_total) {
#endif
// A simple wrapper class around the calling convention information
// that allows sharing of adapters for the same calling convention.
class AdapterFingerPrint : public CHeapObj {
private:
union {
signed char _compact[12];
int _compact_int[3];
intptr_t* _fingerprint;
} _value;
int _length; // A negative length indicates that _value._fingerprint is the array.
// Otherwise it's in the compact form.
public:
AdapterFingerPrint(int total_args_passed, VMRegPair* regs) {
assert(sizeof(_value._compact) == sizeof(_value._compact_int), "must match");
_length = total_args_passed * 2;
if (_length < (int)sizeof(_value._compact)) {
_value._compact_int[0] = _value._compact_int[1] = _value._compact_int[2] = 0;
// Storing the signature encoded as signed chars hits about 98%
// of the time.
signed char* ptr = _value._compact;
int o = 0;
for (int i = 0; i < total_args_passed; i++) {
VMRegPair pair = regs[i];
intptr_t v1 = pair.first()->value();
intptr_t v2 = pair.second()->value();
if (v1 == (signed char) v1 &&
v2 == (signed char) v2) {
_value._compact[o++] = v1;
_value._compact[o++] = v2;
} else {
goto big;
}
}
_length = -_length;
return;
}
big:
_value._fingerprint = NEW_C_HEAP_ARRAY(intptr_t, _length);
int o = 0;
for (int i = 0; i < total_args_passed; i++) {
VMRegPair pair = regs[i];
intptr_t v1 = pair.first()->value();
intptr_t v2 = pair.second()->value();
_value._fingerprint[o++] = v1;
_value._fingerprint[o++] = v2;
}
}
AdapterFingerPrint(AdapterFingerPrint* orig) {
_length = orig->_length;
_value = orig->_value;
// take ownership of any storage by destroying the length
orig->_length = 0;
}
~AdapterFingerPrint() {
if (_length > 0) {
FREE_C_HEAP_ARRAY(int, _value._fingerprint);
}
}
AdapterFingerPrint* allocate() {
return new AdapterFingerPrint(this);
}
intptr_t value(int index) {
if (_length < 0) {
return _value._compact[index];
}
return _value._fingerprint[index];
}
int length() {
if (_length < 0) return -_length;
return _length;
}
bool is_compact() {
return _length <= 0;
}
unsigned int compute_hash() {
intptr_t hash = 0;
for (int i = 0; i < length(); i++) {
intptr_t v = value(i);
hash = (hash << 8) ^ v ^ (hash >> 5);
}
return (unsigned int)hash;
}
const char* as_string() {
stringStream st;
for (int i = 0; i < length(); i++) {
st.print(PTR_FORMAT, value(i));
}
return st.as_string();
}
bool equals(AdapterFingerPrint* other) {
if (other->_length != _length) {
return false;
}
if (_length < 0) {
return _value._compact_int[0] == other->_value._compact_int[0] &&
_value._compact_int[1] == other->_value._compact_int[1] &&
_value._compact_int[2] == other->_value._compact_int[2];
} else {
for (int i = 0; i < _length; i++) {
if (_value._fingerprint[i] != other->_value._fingerprint[i]) {
return false;
}
}
}
return true;
}
};
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
class AdapterHandlerTable : public BasicHashtable {
friend class AdapterHandlerTableIterator;
private:
#ifdef ASSERT
static int _lookups; // number of calls to lookup
static int _buckets; // number of buckets checked
static int _equals; // number of buckets checked with matching hash
static int _hits; // number of successful lookups
static int _compact; // number of equals calls with compact signature
#endif
AdapterHandlerEntry* bucket(int i) {
return (AdapterHandlerEntry*)BasicHashtable::bucket(i);
}
public:
AdapterHandlerTable()
: BasicHashtable(293, sizeof(AdapterHandlerEntry)) { }
// Create a new entry suitable for insertion in the table
AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash());
entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
return entry;
}
// Insert an entry into the table
void add(AdapterHandlerEntry* entry) {
int index = hash_to_index(entry->hash());
add_entry(index, entry);
}
// Find a entry with the same fingerprint if it exists
AdapterHandlerEntry* lookup(int total_args_passed, VMRegPair* regs) {
debug_only(_lookups++);
AdapterFingerPrint fp(total_args_passed, regs);
unsigned int hash = fp.compute_hash();
int index = hash_to_index(hash);
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
debug_only(_buckets++);
if (e->hash() == hash) {
debug_only(_equals++);
if (fp.equals(e->fingerprint())) {
#ifdef ASSERT
if (fp.is_compact()) _compact++;
_hits++;
#endif
return e;
}
}
}
return NULL;
}
void print_statistics() {
ResourceMark rm;
int longest = 0;
int empty = 0;
int total = 0;
int nonempty = 0;
for (int index = 0; index < table_size(); index++) {
int count = 0;
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
count++;
}
if (count != 0) nonempty++;
if (count == 0) empty++;
if (count > longest) longest = count;
total += count;
}
tty->print_cr("AdapterHandlerTable: empty %d longest %d total %d average %f",
empty, longest, total, total / (double)nonempty);
#ifdef ASSERT
tty->print_cr("AdapterHandlerTable: lookups %d buckets %d equals %d hits %d compact %d",
_lookups, _buckets, _equals, _hits, _compact);
#endif
}
};
#ifdef ASSERT
int AdapterHandlerTable::_lookups;
int AdapterHandlerTable::_buckets;
int AdapterHandlerTable::_equals;
int AdapterHandlerTable::_hits;
int AdapterHandlerTable::_compact;
class AdapterHandlerTableIterator : public StackObj {
private:
AdapterHandlerTable* _table;
int _index;
AdapterHandlerEntry* _current;
void scan() {
while (_index < _table->table_size()) {
AdapterHandlerEntry* a = _table->bucket(_index);
if (a != NULL) {
_current = a;
return;
}
_index++;
}
}
public:
AdapterHandlerTableIterator(AdapterHandlerTable* table): _table(table), _index(0), _current(NULL) {
scan();
}
bool has_next() {
return _current != NULL;
}
AdapterHandlerEntry* next() {
if (_current != NULL) {
AdapterHandlerEntry* result = _current;
_current = _current->next();
if (_current == NULL) scan();
return result;
} else {
return NULL;
}
}
};
#endif
// ---------------------------------------------------------------------------
// Implementation of AdapterHandlerLibrary
const char* AdapterHandlerEntry::name = "I2C/C2I adapters";
GrowableArray<uint64_t>* AdapterHandlerLibrary::_fingerprints = NULL;
GrowableArray<AdapterHandlerEntry* >* AdapterHandlerLibrary::_handlers = NULL;
AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL;
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL;
const int AdapterHandlerLibrary_size = 16*K;
BufferBlob* AdapterHandlerLibrary::_buffer = NULL;
......@@ -1796,28 +2045,31 @@ BufferBlob* AdapterHandlerLibrary::buffer_blob() {
}
void AdapterHandlerLibrary::initialize() {
if (_fingerprints != NULL) return;
_fingerprints = new(ResourceObj::C_HEAP)GrowableArray<uint64_t>(32, true);
_handlers = new(ResourceObj::C_HEAP)GrowableArray<AdapterHandlerEntry*>(32, true);
// Index 0 reserved for the slow path handler
_fingerprints->append(0/*the never-allowed 0 fingerprint*/);
_handlers->append(NULL);
if (_adapters != NULL) return;
_adapters = new AdapterHandlerTable();
// Create a special handler for abstract methods. Abstract methods
// are never compiled so an i2c entry is somewhat meaningless, but
// fill it in with something appropriate just in case. Pass handle
// wrong method for the c2i transitions.
address wrong_method = SharedRuntime::get_handle_wrong_method_stub();
_fingerprints->append(0/*the never-allowed 0 fingerprint*/);
assert(_handlers->length() == AbstractMethodHandler, "in wrong slot");
_handlers->append(new AdapterHandlerEntry(StubRoutines::throw_AbstractMethodError_entry(),
wrong_method, wrong_method));
_abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL),
StubRoutines::throw_AbstractMethodError_entry(),
wrong_method, wrong_method);
}
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
address c2i_unverified_entry) {
return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
}
int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
// Use customized signature handler. Need to lock around updates to the
// _fingerprints array (it is not safe for concurrent readers and a single
// writer: this can be fixed if it becomes a problem).
AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) {
// Use customized signature handler. Need to lock around updates to
// the AdapterHandlerTable (it is not safe for concurrent readers
// and a single writer: this could be fixed if it becomes a
// problem).
// Get the address of the ic_miss handlers before we grab the
// AdapterHandlerLibrary_lock. This fixes bug 6236259 which
......@@ -1828,47 +2080,49 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
address ic_miss = SharedRuntime::get_ic_miss_stub();
assert(ic_miss != NULL, "must have handler");
int result;
ResourceMark rm;
NOT_PRODUCT(int code_size);
BufferBlob *B = NULL;
AdapterHandlerEntry* entry = NULL;
uint64_t fingerprint;
AdapterFingerPrint* fingerprint = NULL;
{
MutexLocker mu(AdapterHandlerLibrary_lock);
// make sure data structure is initialized
initialize();
if (method->is_abstract()) {
return AbstractMethodHandler;
return _abstract_method_handler;
}
// Fill in the signature array, for the calling-convention call.
int total_args_passed = method->size_of_parameters(); // All args on stack
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
int i = 0;
if (!method->is_static()) // Pass in receiver first
sig_bt[i++] = T_OBJECT;
for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) {
sig_bt[i++] = ss.type(); // Collect remaining bits of signature
if (ss.type() == T_LONG || ss.type() == T_DOUBLE)
sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots
}
assert(i == total_args_passed, "");
// Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false);
// Lookup method signature's fingerprint
fingerprint = Fingerprinter(method).fingerprint();
assert( fingerprint != CONST64( 0), "no zero fingerprints allowed" );
// Fingerprints are small fixed-size condensed representations of
// signatures. If the signature is too large, it won't fit in a
// fingerprint. Signatures which cannot support a fingerprint get a new i2c
// adapter gen'd each time, instead of searching the cache for one. This -1
// game can be avoided if I compared signatures instead of using
// fingerprints. However, -1 fingerprints are very rare.
if( fingerprint != UCONST64(-1) ) { // If this is a cache-able fingerprint
// Turns out i2c adapters do not care what the return value is. Mask it
// out so signatures that only differ in return type will share the same
// adapter.
fingerprint &= ~(SignatureIterator::result_feature_mask << SignatureIterator::static_feature_size);
// Search for a prior existing i2c/c2i adapter
int index = _fingerprints->find(fingerprint);
if( index >= 0 ) return index; // Found existing handlers?
} else {
// Annoyingly, I end up adding -1 fingerprints to the array of handlers,
// because I need a unique handler index. It cannot be scanned for
// because all -1's look alike. Instead, the matching index is passed out
// and immediately used to collect the 2 return values (the c2i and i2c
// adapters).
entry = _adapters->lookup(total_args_passed, regs);
if (entry != NULL) {
return entry;
}
// Make a C heap allocated version of the fingerprint to store in the adapter
fingerprint = new AdapterFingerPrint(total_args_passed, regs);
// Create I2C & C2I handlers
ResourceMark rm;
BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
if (buf != NULL) {
......@@ -1878,32 +2132,12 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
sizeof(buffer_locs)/sizeof(relocInfo));
MacroAssembler _masm(&buffer);
// Fill in the signature array, for the calling-convention call.
int total_args_passed = method->size_of_parameters(); // All args on stack
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType,total_args_passed);
VMRegPair * regs = NEW_RESOURCE_ARRAY(VMRegPair ,total_args_passed);
int i=0;
if( !method->is_static() ) // Pass in receiver first
sig_bt[i++] = T_OBJECT;
for( SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) {
sig_bt[i++] = ss.type(); // Collect remaining bits of signature
if( ss.type() == T_LONG || ss.type() == T_DOUBLE )
sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots
}
assert( i==total_args_passed, "" );
// Now get the re-packed compiled-Java layout.
int comp_args_on_stack;
// Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false);
entry = SharedRuntime::generate_i2c2i_adapters(&_masm,
total_args_passed,
comp_args_on_stack,
sig_bt,
regs);
regs,
fingerprint);
B = BufferBlob::create(AdapterHandlerEntry::name, &buffer);
NOT_PRODUCT(code_size = buffer.code_size());
......@@ -1925,36 +2159,31 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
UseCompiler = false;
AlwaysCompileLoopMethods = false;
}
return 0; // Out of CodeCache space (_handlers[0] == NULL)
return NULL; // Out of CodeCache space
}
entry->relocate(B->instructions_begin());
#ifndef PRODUCT
// debugging suppport
if (PrintAdapterHandlers) {
tty->cr();
tty->print_cr("i2c argument handler #%d for: %s %s (fingerprint = 0x%llx, %d bytes generated)",
_handlers->length(), (method->is_static() ? "static" : "receiver"),
method->signature()->as_C_string(), fingerprint, code_size );
tty->print_cr("i2c argument handler #%d for: %s %s (fingerprint = %s, %d bytes generated)",
_adapters->number_of_entries(), (method->is_static() ? "static" : "receiver"),
method->signature()->as_C_string(), fingerprint->as_string(), code_size );
tty->print_cr("c2i argument handler starts at %p",entry->get_c2i_entry());
Disassembler::decode(entry->get_i2c_entry(), entry->get_i2c_entry() + code_size);
}
#endif
// add handlers to library
_fingerprints->append(fingerprint);
_handlers->append(entry);
// set handler index
assert(_fingerprints->length() == _handlers->length(), "sanity check");
result = _fingerprints->length() - 1;
_adapters->add(entry);
}
// Outside of the lock
if (B != NULL) {
char blob_id[256];
jio_snprintf(blob_id,
sizeof(blob_id),
"%s(" PTR64_FORMAT ")@" PTR_FORMAT,
"%s(%s)@" PTR_FORMAT,
AdapterHandlerEntry::name,
fingerprint,
fingerprint->as_string(),
B->instructions_begin());
VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
......@@ -1965,7 +2194,7 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
B->instructions_end());
}
}
return result;
return entry;
}
void AdapterHandlerEntry::relocate(address new_base) {
......@@ -2308,30 +2537,31 @@ JRT_END
#ifndef PRODUCT
bool AdapterHandlerLibrary::contains(CodeBlob* b) {
if (_handlers == NULL) return false;
for (int i = 0 ; i < _handlers->length() ; i++) {
AdapterHandlerEntry* a = get_entry(i);
if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) return true;
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if ( b == CodeCache::find_blob(a->get_i2c_entry()) ) return true;
}
return false;
}
void AdapterHandlerLibrary::print_handler(CodeBlob* b) {
for (int i = 0 ; i < _handlers->length() ; i++) {
AdapterHandlerEntry* a = get_entry(i);
if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if ( b == CodeCache::find_blob(a->get_i2c_entry()) ) {
tty->print("Adapter for signature: ");
// Fingerprinter::print(_fingerprints->at(i));
tty->print("0x%" FORMAT64_MODIFIER "x", _fingerprints->at(i));
tty->print_cr(" i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
tty->print_cr("%s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
a->fingerprint()->as_string(),
a->get_i2c_entry(), a->get_c2i_entry(), a->get_c2i_unverified_entry());
return;
}
}
assert(false, "Should have found handler");
}
void AdapterHandlerLibrary::print_statistics() {
_adapters->print_statistics();
}
#endif /* PRODUCT */
/*
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2010 Sun Microsystems, Inc. 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
......@@ -23,6 +23,8 @@
*/
class AdapterHandlerEntry;
class AdapterHandlerTable;
class AdapterFingerPrint;
class vframeStream;
// Runtime is the base class for various runtime interfaces
......@@ -337,7 +339,8 @@ class SharedRuntime: AllStatic {
int total_args_passed,
int max_arg,
const BasicType *sig_bt,
const VMRegPair *regs);
const VMRegPair *regs,
AdapterFingerPrint* fingerprint);
// OSR support
......@@ -528,28 +531,41 @@ class SharedRuntime: AllStatic {
// used by the adapters. The code generation happens here because it's very
// similar to what the adapters have to do.
class AdapterHandlerEntry : public CHeapObj {
class AdapterHandlerEntry : public BasicHashtableEntry {
friend class AdapterHandlerTable;
private:
AdapterFingerPrint* _fingerprint;
address _i2c_entry;
address _c2i_entry;
address _c2i_unverified_entry;
public:
void init(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
_fingerprint = fingerprint;
_i2c_entry = i2c_entry;
_c2i_entry = c2i_entry;
_c2i_unverified_entry = c2i_unverified_entry;
}
// should never be used
AdapterHandlerEntry();
public:
// The name we give all buffer blobs
static const char* name;
AdapterHandlerEntry(address i2c_entry, address c2i_entry, address c2i_unverified_entry):
_i2c_entry(i2c_entry),
_c2i_entry(c2i_entry),
_c2i_unverified_entry(c2i_unverified_entry) {
}
address get_i2c_entry() { return _i2c_entry; }
address get_c2i_entry() { return _c2i_entry; }
address get_c2i_unverified_entry() { return _c2i_unverified_entry; }
void relocate(address new_base);
AdapterFingerPrint* fingerprint() { return _fingerprint; }
AdapterHandlerEntry* next() {
return (AdapterHandlerEntry*)BasicHashtableEntry::next();
}
#ifndef PRODUCT
void print();
#endif /* PRODUCT */
......@@ -558,30 +574,18 @@ class AdapterHandlerEntry : public CHeapObj {
class AdapterHandlerLibrary: public AllStatic {
private:
static BufferBlob* _buffer; // the temporary code buffer in CodeCache
static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection
static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers
enum {
AbstractMethodHandler = 1 // special handler for abstract methods
};
static AdapterHandlerTable* _adapters;
static AdapterHandlerEntry* _abstract_method_handler;
static BufferBlob* buffer_blob();
static void initialize();
static int get_create_adapter_index(methodHandle method);
static address get_i2c_entry( int index ) {
return get_entry(index)->get_i2c_entry();
}
static address get_c2i_entry( int index ) {
return get_entry(index)->get_c2i_entry();
}
static address get_c2i_unverified_entry( int index ) {
return get_entry(index)->get_c2i_unverified_entry();
}
public:
static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); }
static AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry, address c2i_entry, address c2i_unverified_entry);
static nmethod* create_native_wrapper(methodHandle method);
static AdapterHandlerEntry* get_adapter(methodHandle method) {
return get_entry(get_create_adapter_index(method));
}
static AdapterHandlerEntry* get_adapter(methodHandle method);
#ifdef HAVE_DTRACE_H
static nmethod* create_dtrace_nmethod (methodHandle method);
#endif // HAVE_DTRACE_H
......@@ -589,6 +593,7 @@ class AdapterHandlerLibrary: public AllStatic {
#ifndef PRODUCT
static void print_handler(CodeBlob* b);
static bool contains(CodeBlob* b);
static void print_statistics();
#endif /* PRODUCT */
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册