src/share/vm/runtime/sharedRuntime.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/runtime/sharedRuntime.cpp Tue Feb 2 00:30:01 2010
--- new/src/share/vm/runtime/sharedRuntime.cpp Tue Feb 2 00:30:01 2010
*** 1785,1856 ****
--- 1785,1873 ----
// 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;
! int _compact[3];
! int* _fingerprint;
} _value;
! int _length; // A negative length indicates that _value._fingerprint is the array.
! // Otherwise it's in the compact form.
! int _length; // A negative length indicates the fingerprint is in the compact form,
! // Otherwise _value._fingerprint is the array.
+ // Remap BasicTypes that are handled equivalently by the adapters.
+ // These are correct for the current system but someday it might be
+ // necessary to make this mapping platform dependent.
+ static BasicType adapter_encoding(BasicType in) {
+ assert((~0xf & in) == 0, "must fit in 4 bits");
+ switch(in) {
+ case T_BOOLEAN:
+ case T_BYTE:
+ case T_SHORT:
+ case T_CHAR:
+ // There are all promoted to T_INT in the calling convention
+ return T_INT;
+
+ case T_OBJECT:
+ case T_ARRAY:
+ if (!TaggedStackInterpreter) {
+ #ifdef _LP64
+ return T_LONG;
+ #else
+ return T_INT;
+ #endif
+ }
+ return T_OBJECT;
+
+ case T_INT:
+ case T_LONG:
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_VOID:
+ return in;
+
+ default:
+ ShouldNotReachHere();
+ return T_CONFLICT;
+ }
+ }
+
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;
! AdapterFingerPrint(int total_args_passed, BasicType* sig_bt) {
+ // The fingerprint is based on the BasicType signature encoded
+ // into an array of ints with four entries per int.
! int* ptr;
! int l = (total_args_passed + 3) >> 2;
+ if (l <= (int)sizeof(_value._compact) / sizeof(int)) {
+ _value._compact[0] = _value._compact[1] = _value._compact[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;
! _length = -l;
! ptr = _value._compact;
} else {
! goto big;
! _length = l;
+ _value._fingerprint = NEW_C_HEAP_ARRAY(int, _length);
+ ptr = _value._fingerprint;
}
+
+ int i = 0;
+ for (int o = 0; o < l;) {
+ int value = 0;
+ for (int i = 0; i < 4; i++) {
+ if (i + o * 4 < total_args_passed)
+ value = (value << 4) | adapter_encoding(sig_bt[i + o * 4]);
}
! _length = -_length;
return;
! ptr[o++] = value;
}
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) {
! int value(int index) {
if (_length < 0) {
return _value._compact[index];
}
return _value._fingerprint[index];
}
*** 1862,1874 ****
--- 1879,1891 ----
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;
}
*** 1883,1895 ****
--- 1900,1912 ----
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];
! _value._compact[1] == other->_value._compact[1] &&
! _value._compact[2] == other->_value._compact[2];
} else {
for (int i = 0; i < _length; i++) {
if (_value._fingerprint[i] != other->_value._fingerprint[i]) {
return false;
}
*** 1934,1946 ****
--- 1951,1963 ----
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) {
! AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
debug_only(_lookups++);
! AdapterFingerPrint fp(total_args_passed, regs);
! AdapterFingerPrint fp(total_args_passed, sig_bt);
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) {
*** 2089,2098 ****
--- 2106,2117 ----
{
MutexLocker mu(AdapterHandlerLibrary_lock);
// make sure data structure is initialized
initialize();
+ AdapterHandlerEntry* cached_entry = NULL;
+
if (method->is_abstract()) {
return _abstract_method_handler;
}
// Fill in the signature array, for the calling-convention call.
*** 2108,2128 ****
--- 2127,2152 ----
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
! entry = _adapters->lookup(total_args_passed, regs);
! entry = _adapters->lookup(total_args_passed, sig_bt);
if (entry != NULL) {
+ if (UseNewCode) {
+ cached_entry = entry;
+ entry = NULL;
+ } else {
return entry;
}
+ }
+ // 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);
+
// Make a C heap allocated version of the fingerprint to store in the adapter
! fingerprint = new AdapterFingerPrint(total_args_passed, regs);
! fingerprint = new AdapterFingerPrint(total_args_passed, sig_bt);
// Create I2C & C2I handlers
BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
if (buf != NULL) {
*** 2137,2146 ****
--- 2161,2178 ----
comp_args_on_stack,
sig_bt,
regs,
fingerprint);
+ if (cached_entry != NULL) {
+ assert(cached_entry->compare_code(buf->instructions_begin(), buffer.code_size(), total_args_passed, sig_bt),
+ "code must match");
+ _adapters->free_entry(entry);
+ return cached_entry;
+ } else if (UseNewCode) {
+ entry->save_code(buf->instructions_begin(), buffer.code_size(), total_args_passed, sig_bt);
+ }
B = BufferBlob::create(AdapterHandlerEntry::name, &buffer);
NOT_PRODUCT(code_size = buffer.code_size());
}
if (B == NULL) {
// CodeCache is full, disable compilation
*** 2191,2200 ****
--- 2223,2255 ----
_i2c_entry += delta;
_c2i_entry += delta;
_c2i_unverified_entry += delta;
}
+ void AdapterHandlerEntry::save_code(unsigned char* buffer, int length, int total_args_passed, BasicType* sig_bt) {
+ _data = NEW_C_HEAP_ARRAY(unsigned char, length);
+ _data_length = length;
+ memcpy(_data, buffer, length);
+ _total_args_passed = total_args_passed;
+ _saved_sig = NEW_C_HEAP_ARRAY(BasicType, _total_args_passed);
+ memcpy(_saved_sig, sig_bt, _total_args_passed * sizeof(BasicType));
+ }
+
+ bool AdapterHandlerEntry::compare_code(unsigned char* buffer, int length, int total_args_passed, BasicType* sig_bt) {
+ if (length != _data_length) {
+ assert(false, "what");
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (buffer[i] != _data[i]) {
+ assert(false, "what");
+ return false;
+ }
+ }
+ return true;
+ }
+
// Create a native wrapper for this native method. The wrapper converts the
// java compiled calling convention to the native convention, handlizes
// arguments, and transitions to native. On return from the native we transition
// back to java blocking if a safepoint is in progress.
nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method) {
src/share/vm/runtime/sharedRuntime.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File