--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
// 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 @@
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);
}
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
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,
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
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,
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -1249,6 +1249,7 @@
}
int ClassLoader::_compile_the_world_counter = 0;
+static int _codecache_sweep_counter = 0;
void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
int len = (int)strlen(name);
@@ -1293,6 +1294,13 @@
for (int n = 0; n < k->methods()->length(); n++) {
methodHandle m (THREAD, methodOop(k->methods()->obj_at(n)));
if (CompilationPolicy::canBeCompiled(m)) {
+
+ if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) {
+ // Give sweeper a chance to keep up with CTW
+ VM_ForceSafepoint op;
+ VMThread::execute(&op);
+ _codecache_sweep_counter = 0;
+ }
// Force compilation
CompileBroker::compile_method(m, InvocationEntryBci,
methodHandle(), 0, "CTW", THREAD);
--- a/hotspot/src/share/vm/includeDB_core Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/includeDB_core Wed Jan 27 14:06:27 2010 -0800
@@ -921,6 +921,7 @@
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 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
@@ -3725,6 +3727,7 @@
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
@@ -3752,6 +3755,7 @@
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
--- a/hotspot/src/share/vm/oops/methodOop.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/oops/methodOop.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -688,7 +688,7 @@
// 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);
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -2815,6 +2815,15 @@
DebugNonSafepoints = true;
}
+#ifndef PRODUCT
+ if (CompileTheWorld) {
+ // Force NmethodSweeper to sweep whole CodeCache each time.
+ if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
+ NmethodSweepFraction = 1;
+ }
+ }
+#endif
+
if (PrintCommandLineFlags) {
CommandLineFlags::printSetFlags();
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jan 27 14:06:27 2010 -0800
@@ -2447,6 +2447,9 @@
notproduct(bool, CompileTheWorldIgnoreInitErrors, false, \
"Compile all methods although class initializer failed") \
\
+ notproduct(intx, CompileTheWorldSafepointInterval, 100, \
+ "Force a safepoint every n compiles so sweeper can keep up") \
+ \
develop(bool, TraceIterativeGVN, false, \
"Print progress during Iterative Global Value Numbering") \
\
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jan 27 14:06:27 2010 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
#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 @@
}
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);
}
-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::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);
+}
+
+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 @@
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 @@
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 @@
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 @@
B->instructions_end());
}
}
- return result;
+ return entry;
}
void AdapterHandlerEntry::relocate(address new_base) {
@@ -2308,30 +2537,31 @@
#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 */
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Fri Jan 22 15:06:53 2010 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jan 27 14:06:27 2010 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
// 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;
+ 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 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 @@
#ifndef PRODUCT
static void print_handler(CodeBlob* b);
static bool contains(CodeBlob* b);
+ static void print_statistics();
#endif /* PRODUCT */
};