src/share/vm/runtime/sharedRuntime.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6911204 Cdiff src/share/vm/runtime/sharedRuntime.cpp

src/share/vm/runtime/sharedRuntime.cpp

Print this page

        

*** 1785,1856 **** // 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]; } --- 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 { ! int _compact[3]; ! int* _fingerprint; } _value; ! 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, 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. ! _length = -l; ! ptr = _value._compact; } else { ! _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]); } ! ptr[o++] = value; } } ~AdapterFingerPrint() { if (_length > 0) { FREE_C_HEAP_ARRAY(int, _value._fingerprint); } } ! int value(int index) { if (_length < 0) { return _value._compact[index]; } return _value._fingerprint[index]; }
*** 1862,1874 **** 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; } --- 1879,1891 ---- bool is_compact() { return _length <= 0; } unsigned int compute_hash() { ! int hash = 0; for (int i = 0; i < length(); i++) { ! int v = value(i); hash = (hash << 8) ^ v ^ (hash >> 5); } return (unsigned int)hash; }
*** 1883,1895 **** 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; } --- 1900,1912 ---- bool equals(AdapterFingerPrint* other) { if (other->_length != _length) { return false; } if (_length < 0) { ! return _value._compact[0] == other->_value._compact[0] && ! _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 **** 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) { --- 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, BasicType* sig_bt) { debug_only(_lookups++); ! 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 **** 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); 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 BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { --- 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, ""); // Lookup method signature's fingerprint ! 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, 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