Wed, 20 Jan 2010 22:10:33 -0800
6911204: generated adapters with large signatures can fill up the code cache
Reviewed-by: kvn, jrose
1.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Jan 20 12:54:25 2010 -0800 1.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Jan 20 22:10:33 2010 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -1189,7 +1189,8 @@ 1.11 // VMReg max_arg, 1.12 int comp_args_on_stack, // VMRegStackSlots 1.13 const BasicType *sig_bt, 1.14 - const VMRegPair *regs) { 1.15 + const VMRegPair *regs, 1.16 + AdapterFingerPrint* fingerprint) { 1.17 address i2c_entry = __ pc(); 1.18 1.19 AdapterGenerator agen(masm); 1.20 @@ -1258,7 +1259,7 @@ 1.21 agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); 1.22 1.23 __ flush(); 1.24 - return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry); 1.25 + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); 1.26 1.27 } 1.28
2.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jan 20 12:54:25 2010 -0800 2.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jan 20 22:10:33 2010 -0800 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 2.6 + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -907,7 +907,8 @@ 2.11 int total_args_passed, 2.12 int comp_args_on_stack, 2.13 const BasicType *sig_bt, 2.14 - const VMRegPair *regs) { 2.15 + const VMRegPair *regs, 2.16 + AdapterFingerPrint* fingerprint) { 2.17 address i2c_entry = __ pc(); 2.18 2.19 gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); 2.20 @@ -954,7 +955,7 @@ 2.21 gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); 2.22 2.23 __ flush(); 2.24 - return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry); 2.25 + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); 2.26 } 2.27 2.28 int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
3.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jan 20 12:54:25 2010 -0800 3.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jan 20 22:10:33 2010 -0800 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 3.6 + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -778,7 +778,8 @@ 3.11 int total_args_passed, 3.12 int comp_args_on_stack, 3.13 const BasicType *sig_bt, 3.14 - const VMRegPair *regs) { 3.15 + const VMRegPair *regs, 3.16 + AdapterFingerPrint* fingerprint) { 3.17 address i2c_entry = __ pc(); 3.18 3.19 gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); 3.20 @@ -824,7 +825,7 @@ 3.21 gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); 3.22 3.23 __ flush(); 3.24 - return new AdapterHandlerEntry(i2c_entry, c2i_entry, c2i_unverified_entry); 3.25 + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); 3.26 } 3.27 3.28 int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
4.1 --- a/src/share/vm/includeDB_core Wed Jan 20 12:54:25 2010 -0800 4.2 +++ b/src/share/vm/includeDB_core Wed Jan 20 22:10:33 2010 -0800 4.3 @@ -921,6 +921,7 @@ 4.4 4.5 classLoader.cpp allocation.inline.hpp 4.6 classLoader.cpp arguments.hpp 4.7 +classLoader.cpp bytecodeStream.hpp 4.8 classLoader.cpp classFileParser.hpp 4.9 classLoader.cpp classFileStream.hpp 4.10 classLoader.cpp classLoader.hpp 4.11 @@ -948,6 +949,7 @@ 4.12 classLoader.cpp management.hpp 4.13 classLoader.cpp oop.inline.hpp 4.14 classLoader.cpp oopFactory.hpp 4.15 +classLoader.cpp oopMapCache.hpp 4.16 classLoader.cpp os_<os_family>.inline.hpp 4.17 classLoader.cpp symbolOop.hpp 4.18 classLoader.cpp systemDictionary.hpp 4.19 @@ -3724,6 +3726,7 @@ 4.20 sharedRuntime.cpp forte.hpp 4.21 sharedRuntime.cpp gcLocker.inline.hpp 4.22 sharedRuntime.cpp handles.inline.hpp 4.23 +sharedRuntime.cpp hashtable.inline.hpp 4.24 sharedRuntime.cpp init.hpp 4.25 sharedRuntime.cpp interfaceSupport.hpp 4.26 sharedRuntime.cpp interpreterRuntime.hpp 4.27 @@ -3751,6 +3754,7 @@ 4.28 sharedRuntime.hpp allocation.hpp 4.29 sharedRuntime.hpp bytecodeHistogram.hpp 4.30 sharedRuntime.hpp bytecodeTracer.hpp 4.31 +sharedRuntime.hpp hashtable.hpp 4.32 sharedRuntime.hpp linkResolver.hpp 4.33 sharedRuntime.hpp resourceArea.hpp 4.34 sharedRuntime.hpp threadLocalStorage.hpp
5.1 --- a/src/share/vm/oops/methodOop.cpp Wed Jan 20 12:54:25 2010 -0800 5.2 +++ b/src/share/vm/oops/methodOop.cpp Wed Jan 20 22:10:33 2010 -0800 5.3 @@ -688,7 +688,7 @@ 5.4 // so making them eagerly shouldn't be too expensive. 5.5 AdapterHandlerEntry* adapter = AdapterHandlerLibrary::get_adapter(mh); 5.6 if (adapter == NULL ) { 5.7 - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); 5.8 + THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "out of space in CodeCache for adapters"); 5.9 } 5.10 5.11 mh->set_adapter_entry(adapter);
6.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Wed Jan 20 12:54:25 2010 -0800 6.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Jan 20 22:10:33 2010 -0800 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 6.6 + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -1680,6 +1680,8 @@ 6.11 if( _find_handler_ctr ) tty->print_cr("%5d find exception handler", _find_handler_ctr ); 6.12 if( _rethrow_ctr ) tty->print_cr("%5d rethrow handler", _rethrow_ctr ); 6.13 6.14 + AdapterHandlerLibrary::print_statistics(); 6.15 + 6.16 if (xtty != NULL) xtty->tail("statistics"); 6.17 } 6.18 6.19 @@ -1780,11 +1782,258 @@ 6.20 #endif 6.21 6.22 6.23 +// A simple wrapper class around the calling convention information 6.24 +// that allows sharing of adapters for the same calling convention. 6.25 +class AdapterFingerPrint : public CHeapObj { 6.26 + private: 6.27 + union { 6.28 + signed char _compact[12]; 6.29 + int _compact_int[3]; 6.30 + intptr_t* _fingerprint; 6.31 + } _value; 6.32 + int _length; // A negative length indicates that _value._fingerprint is the array. 6.33 + // Otherwise it's in the compact form. 6.34 + 6.35 + public: 6.36 + AdapterFingerPrint(int total_args_passed, VMRegPair* regs) { 6.37 + assert(sizeof(_value._compact) == sizeof(_value._compact_int), "must match"); 6.38 + _length = total_args_passed * 2; 6.39 + if (_length < (int)sizeof(_value._compact)) { 6.40 + _value._compact_int[0] = _value._compact_int[1] = _value._compact_int[2] = 0; 6.41 + // Storing the signature encoded as signed chars hits about 98% 6.42 + // of the time. 6.43 + signed char* ptr = _value._compact; 6.44 + int o = 0; 6.45 + for (int i = 0; i < total_args_passed; i++) { 6.46 + VMRegPair pair = regs[i]; 6.47 + intptr_t v1 = pair.first()->value(); 6.48 + intptr_t v2 = pair.second()->value(); 6.49 + if (v1 == (signed char) v1 && 6.50 + v2 == (signed char) v2) { 6.51 + _value._compact[o++] = v1; 6.52 + _value._compact[o++] = v2; 6.53 + } else { 6.54 + goto big; 6.55 + } 6.56 + } 6.57 + _length = -_length; 6.58 + return; 6.59 + } 6.60 + big: 6.61 + _value._fingerprint = NEW_C_HEAP_ARRAY(intptr_t, _length); 6.62 + int o = 0; 6.63 + for (int i = 0; i < total_args_passed; i++) { 6.64 + VMRegPair pair = regs[i]; 6.65 + intptr_t v1 = pair.first()->value(); 6.66 + intptr_t v2 = pair.second()->value(); 6.67 + _value._fingerprint[o++] = v1; 6.68 + _value._fingerprint[o++] = v2; 6.69 + } 6.70 + } 6.71 + 6.72 + AdapterFingerPrint(AdapterFingerPrint* orig) { 6.73 + _length = orig->_length; 6.74 + _value = orig->_value; 6.75 + // take ownership of any storage by destroying the length 6.76 + orig->_length = 0; 6.77 + } 6.78 + 6.79 + ~AdapterFingerPrint() { 6.80 + if (_length > 0) { 6.81 + FREE_C_HEAP_ARRAY(int, _value._fingerprint); 6.82 + } 6.83 + } 6.84 + 6.85 + AdapterFingerPrint* allocate() { 6.86 + return new AdapterFingerPrint(this); 6.87 + } 6.88 + 6.89 + intptr_t value(int index) { 6.90 + if (_length < 0) { 6.91 + return _value._compact[index]; 6.92 + } 6.93 + return _value._fingerprint[index]; 6.94 + } 6.95 + int length() { 6.96 + if (_length < 0) return -_length; 6.97 + return _length; 6.98 + } 6.99 + 6.100 + bool is_compact() { 6.101 + return _length <= 0; 6.102 + } 6.103 + 6.104 + unsigned int compute_hash() { 6.105 + intptr_t hash = 0; 6.106 + for (int i = 0; i < length(); i++) { 6.107 + intptr_t v = value(i); 6.108 + hash = (hash << 8) ^ v ^ (hash >> 5); 6.109 + } 6.110 + return (unsigned int)hash; 6.111 + } 6.112 + 6.113 + const char* as_string() { 6.114 + stringStream st; 6.115 + for (int i = 0; i < length(); i++) { 6.116 + st.print(PTR_FORMAT, value(i)); 6.117 + } 6.118 + return st.as_string(); 6.119 + } 6.120 + 6.121 + bool equals(AdapterFingerPrint* other) { 6.122 + if (other->_length != _length) { 6.123 + return false; 6.124 + } 6.125 + if (_length < 0) { 6.126 + return _value._compact_int[0] == other->_value._compact_int[0] && 6.127 + _value._compact_int[1] == other->_value._compact_int[1] && 6.128 + _value._compact_int[2] == other->_value._compact_int[2]; 6.129 + } else { 6.130 + for (int i = 0; i < _length; i++) { 6.131 + if (_value._fingerprint[i] != other->_value._fingerprint[i]) { 6.132 + return false; 6.133 + } 6.134 + } 6.135 + } 6.136 + return true; 6.137 + } 6.138 +}; 6.139 + 6.140 + 6.141 +// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries 6.142 +class AdapterHandlerTable : public BasicHashtable { 6.143 + friend class AdapterHandlerTableIterator; 6.144 + 6.145 + private: 6.146 + 6.147 +#ifdef ASSERT 6.148 + static int _lookups; // number of calls to lookup 6.149 + static int _buckets; // number of buckets checked 6.150 + static int _equals; // number of buckets checked with matching hash 6.151 + static int _hits; // number of successful lookups 6.152 + static int _compact; // number of equals calls with compact signature 6.153 +#endif 6.154 + 6.155 + AdapterHandlerEntry* bucket(int i) { 6.156 + return (AdapterHandlerEntry*)BasicHashtable::bucket(i); 6.157 + } 6.158 + 6.159 + public: 6.160 + AdapterHandlerTable() 6.161 + : BasicHashtable(293, sizeof(AdapterHandlerEntry)) { } 6.162 + 6.163 + // Create a new entry suitable for insertion in the table 6.164 + AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) { 6.165 + AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); 6.166 + entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); 6.167 + return entry; 6.168 + } 6.169 + 6.170 + // Insert an entry into the table 6.171 + void add(AdapterHandlerEntry* entry) { 6.172 + int index = hash_to_index(entry->hash()); 6.173 + add_entry(index, entry); 6.174 + } 6.175 + 6.176 + // Find a entry with the same fingerprint if it exists 6.177 + AdapterHandlerEntry* lookup(int total_args_passed, VMRegPair* regs) { 6.178 + debug_only(_lookups++); 6.179 + AdapterFingerPrint fp(total_args_passed, regs); 6.180 + unsigned int hash = fp.compute_hash(); 6.181 + int index = hash_to_index(hash); 6.182 + for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) { 6.183 + debug_only(_buckets++); 6.184 + if (e->hash() == hash) { 6.185 + debug_only(_equals++); 6.186 + if (fp.equals(e->fingerprint())) { 6.187 +#ifdef ASSERT 6.188 + if (fp.is_compact()) _compact++; 6.189 + _hits++; 6.190 +#endif 6.191 + return e; 6.192 + } 6.193 + } 6.194 + } 6.195 + return NULL; 6.196 + } 6.197 + 6.198 + void print_statistics() { 6.199 + ResourceMark rm; 6.200 + int longest = 0; 6.201 + int empty = 0; 6.202 + int total = 0; 6.203 + int nonempty = 0; 6.204 + for (int index = 0; index < table_size(); index++) { 6.205 + int count = 0; 6.206 + for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) { 6.207 + count++; 6.208 + } 6.209 + if (count != 0) nonempty++; 6.210 + if (count == 0) empty++; 6.211 + if (count > longest) longest = count; 6.212 + total += count; 6.213 + } 6.214 + tty->print_cr("AdapterHandlerTable: empty %d longest %d total %d average %f", 6.215 + empty, longest, total, total / (double)nonempty); 6.216 +#ifdef ASSERT 6.217 + tty->print_cr("AdapterHandlerTable: lookups %d buckets %d equals %d hits %d compact %d", 6.218 + _lookups, _buckets, _equals, _hits, _compact); 6.219 +#endif 6.220 + } 6.221 +}; 6.222 + 6.223 + 6.224 +#ifdef ASSERT 6.225 + 6.226 +int AdapterHandlerTable::_lookups; 6.227 +int AdapterHandlerTable::_buckets; 6.228 +int AdapterHandlerTable::_equals; 6.229 +int AdapterHandlerTable::_hits; 6.230 +int AdapterHandlerTable::_compact; 6.231 + 6.232 +class AdapterHandlerTableIterator : public StackObj { 6.233 + private: 6.234 + AdapterHandlerTable* _table; 6.235 + int _index; 6.236 + AdapterHandlerEntry* _current; 6.237 + 6.238 + void scan() { 6.239 + while (_index < _table->table_size()) { 6.240 + AdapterHandlerEntry* a = _table->bucket(_index); 6.241 + if (a != NULL) { 6.242 + _current = a; 6.243 + return; 6.244 + } 6.245 + _index++; 6.246 + } 6.247 + } 6.248 + 6.249 + public: 6.250 + AdapterHandlerTableIterator(AdapterHandlerTable* table): _table(table), _index(0), _current(NULL) { 6.251 + scan(); 6.252 + } 6.253 + bool has_next() { 6.254 + return _current != NULL; 6.255 + } 6.256 + AdapterHandlerEntry* next() { 6.257 + if (_current != NULL) { 6.258 + AdapterHandlerEntry* result = _current; 6.259 + _current = _current->next(); 6.260 + if (_current == NULL) scan(); 6.261 + return result; 6.262 + } else { 6.263 + return NULL; 6.264 + } 6.265 + } 6.266 +}; 6.267 +#endif 6.268 + 6.269 + 6.270 // --------------------------------------------------------------------------- 6.271 // Implementation of AdapterHandlerLibrary 6.272 const char* AdapterHandlerEntry::name = "I2C/C2I adapters"; 6.273 -GrowableArray<uint64_t>* AdapterHandlerLibrary::_fingerprints = NULL; 6.274 -GrowableArray<AdapterHandlerEntry* >* AdapterHandlerLibrary::_handlers = NULL; 6.275 +AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL; 6.276 +AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL; 6.277 const int AdapterHandlerLibrary_size = 16*K; 6.278 BufferBlob* AdapterHandlerLibrary::_buffer = NULL; 6.279 6.280 @@ -1796,28 +2045,31 @@ 6.281 } 6.282 6.283 void AdapterHandlerLibrary::initialize() { 6.284 - if (_fingerprints != NULL) return; 6.285 - _fingerprints = new(ResourceObj::C_HEAP)GrowableArray<uint64_t>(32, true); 6.286 - _handlers = new(ResourceObj::C_HEAP)GrowableArray<AdapterHandlerEntry*>(32, true); 6.287 - // Index 0 reserved for the slow path handler 6.288 - _fingerprints->append(0/*the never-allowed 0 fingerprint*/); 6.289 - _handlers->append(NULL); 6.290 + if (_adapters != NULL) return; 6.291 + _adapters = new AdapterHandlerTable(); 6.292 6.293 // Create a special handler for abstract methods. Abstract methods 6.294 // are never compiled so an i2c entry is somewhat meaningless, but 6.295 // fill it in with something appropriate just in case. Pass handle 6.296 // wrong method for the c2i transitions. 6.297 address wrong_method = SharedRuntime::get_handle_wrong_method_stub(); 6.298 - _fingerprints->append(0/*the never-allowed 0 fingerprint*/); 6.299 - assert(_handlers->length() == AbstractMethodHandler, "in wrong slot"); 6.300 - _handlers->append(new AdapterHandlerEntry(StubRoutines::throw_AbstractMethodError_entry(), 6.301 - wrong_method, wrong_method)); 6.302 + _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL), 6.303 + StubRoutines::throw_AbstractMethodError_entry(), 6.304 + wrong_method, wrong_method); 6.305 } 6.306 6.307 -int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) { 6.308 - // Use customized signature handler. Need to lock around updates to the 6.309 - // _fingerprints array (it is not safe for concurrent readers and a single 6.310 - // writer: this can be fixed if it becomes a problem). 6.311 +AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint, 6.312 + address i2c_entry, 6.313 + address c2i_entry, 6.314 + address c2i_unverified_entry) { 6.315 + return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); 6.316 +} 6.317 + 6.318 +AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { 6.319 + // Use customized signature handler. Need to lock around updates to 6.320 + // the AdapterHandlerTable (it is not safe for concurrent readers 6.321 + // and a single writer: this could be fixed if it becomes a 6.322 + // problem). 6.323 6.324 // Get the address of the ic_miss handlers before we grab the 6.325 // AdapterHandlerLibrary_lock. This fixes bug 6236259 which 6.326 @@ -1828,47 +2080,49 @@ 6.327 address ic_miss = SharedRuntime::get_ic_miss_stub(); 6.328 assert(ic_miss != NULL, "must have handler"); 6.329 6.330 - int result; 6.331 + ResourceMark rm; 6.332 + 6.333 NOT_PRODUCT(int code_size); 6.334 BufferBlob *B = NULL; 6.335 AdapterHandlerEntry* entry = NULL; 6.336 - uint64_t fingerprint; 6.337 + AdapterFingerPrint* fingerprint = NULL; 6.338 { 6.339 MutexLocker mu(AdapterHandlerLibrary_lock); 6.340 // make sure data structure is initialized 6.341 initialize(); 6.342 6.343 if (method->is_abstract()) { 6.344 - return AbstractMethodHandler; 6.345 + return _abstract_method_handler; 6.346 } 6.347 6.348 + // Fill in the signature array, for the calling-convention call. 6.349 + int total_args_passed = method->size_of_parameters(); // All args on stack 6.350 + 6.351 + BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed); 6.352 + VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed); 6.353 + int i = 0; 6.354 + if (!method->is_static()) // Pass in receiver first 6.355 + sig_bt[i++] = T_OBJECT; 6.356 + for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) { 6.357 + sig_bt[i++] = ss.type(); // Collect remaining bits of signature 6.358 + if (ss.type() == T_LONG || ss.type() == T_DOUBLE) 6.359 + sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots 6.360 + } 6.361 + assert(i == total_args_passed, ""); 6.362 + 6.363 + // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage 6.364 + int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false); 6.365 + 6.366 // Lookup method signature's fingerprint 6.367 - fingerprint = Fingerprinter(method).fingerprint(); 6.368 - assert( fingerprint != CONST64( 0), "no zero fingerprints allowed" ); 6.369 - // Fingerprints are small fixed-size condensed representations of 6.370 - // signatures. If the signature is too large, it won't fit in a 6.371 - // fingerprint. Signatures which cannot support a fingerprint get a new i2c 6.372 - // adapter gen'd each time, instead of searching the cache for one. This -1 6.373 - // game can be avoided if I compared signatures instead of using 6.374 - // fingerprints. However, -1 fingerprints are very rare. 6.375 - if( fingerprint != UCONST64(-1) ) { // If this is a cache-able fingerprint 6.376 - // Turns out i2c adapters do not care what the return value is. Mask it 6.377 - // out so signatures that only differ in return type will share the same 6.378 - // adapter. 6.379 - fingerprint &= ~(SignatureIterator::result_feature_mask << SignatureIterator::static_feature_size); 6.380 - // Search for a prior existing i2c/c2i adapter 6.381 - int index = _fingerprints->find(fingerprint); 6.382 - if( index >= 0 ) return index; // Found existing handlers? 6.383 - } else { 6.384 - // Annoyingly, I end up adding -1 fingerprints to the array of handlers, 6.385 - // because I need a unique handler index. It cannot be scanned for 6.386 - // because all -1's look alike. Instead, the matching index is passed out 6.387 - // and immediately used to collect the 2 return values (the c2i and i2c 6.388 - // adapters). 6.389 + entry = _adapters->lookup(total_args_passed, regs); 6.390 + if (entry != NULL) { 6.391 + return entry; 6.392 } 6.393 6.394 + // Make a C heap allocated version of the fingerprint to store in the adapter 6.395 + fingerprint = new AdapterFingerPrint(total_args_passed, regs); 6.396 + 6.397 // Create I2C & C2I handlers 6.398 - ResourceMark rm; 6.399 6.400 BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache 6.401 if (buf != NULL) { 6.402 @@ -1878,32 +2132,12 @@ 6.403 sizeof(buffer_locs)/sizeof(relocInfo)); 6.404 MacroAssembler _masm(&buffer); 6.405 6.406 - // Fill in the signature array, for the calling-convention call. 6.407 - int total_args_passed = method->size_of_parameters(); // All args on stack 6.408 - 6.409 - BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType,total_args_passed); 6.410 - VMRegPair * regs = NEW_RESOURCE_ARRAY(VMRegPair ,total_args_passed); 6.411 - int i=0; 6.412 - if( !method->is_static() ) // Pass in receiver first 6.413 - sig_bt[i++] = T_OBJECT; 6.414 - for( SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) { 6.415 - sig_bt[i++] = ss.type(); // Collect remaining bits of signature 6.416 - if( ss.type() == T_LONG || ss.type() == T_DOUBLE ) 6.417 - sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots 6.418 - } 6.419 - assert( i==total_args_passed, "" ); 6.420 - 6.421 - // Now get the re-packed compiled-Java layout. 6.422 - int comp_args_on_stack; 6.423 - 6.424 - // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage 6.425 - comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false); 6.426 - 6.427 entry = SharedRuntime::generate_i2c2i_adapters(&_masm, 6.428 total_args_passed, 6.429 comp_args_on_stack, 6.430 sig_bt, 6.431 - regs); 6.432 + regs, 6.433 + fingerprint); 6.434 6.435 B = BufferBlob::create(AdapterHandlerEntry::name, &buffer); 6.436 NOT_PRODUCT(code_size = buffer.code_size()); 6.437 @@ -1925,36 +2159,31 @@ 6.438 UseCompiler = false; 6.439 AlwaysCompileLoopMethods = false; 6.440 } 6.441 - return 0; // Out of CodeCache space (_handlers[0] == NULL) 6.442 + return NULL; // Out of CodeCache space 6.443 } 6.444 entry->relocate(B->instructions_begin()); 6.445 #ifndef PRODUCT 6.446 // debugging suppport 6.447 if (PrintAdapterHandlers) { 6.448 tty->cr(); 6.449 - tty->print_cr("i2c argument handler #%d for: %s %s (fingerprint = 0x%llx, %d bytes generated)", 6.450 - _handlers->length(), (method->is_static() ? "static" : "receiver"), 6.451 - method->signature()->as_C_string(), fingerprint, code_size ); 6.452 + tty->print_cr("i2c argument handler #%d for: %s %s (fingerprint = %s, %d bytes generated)", 6.453 + _adapters->number_of_entries(), (method->is_static() ? "static" : "receiver"), 6.454 + method->signature()->as_C_string(), fingerprint->as_string(), code_size ); 6.455 tty->print_cr("c2i argument handler starts at %p",entry->get_c2i_entry()); 6.456 Disassembler::decode(entry->get_i2c_entry(), entry->get_i2c_entry() + code_size); 6.457 } 6.458 #endif 6.459 6.460 - // add handlers to library 6.461 - _fingerprints->append(fingerprint); 6.462 - _handlers->append(entry); 6.463 - // set handler index 6.464 - assert(_fingerprints->length() == _handlers->length(), "sanity check"); 6.465 - result = _fingerprints->length() - 1; 6.466 + _adapters->add(entry); 6.467 } 6.468 // Outside of the lock 6.469 if (B != NULL) { 6.470 char blob_id[256]; 6.471 jio_snprintf(blob_id, 6.472 sizeof(blob_id), 6.473 - "%s(" PTR64_FORMAT ")@" PTR_FORMAT, 6.474 + "%s(%s)@" PTR_FORMAT, 6.475 AdapterHandlerEntry::name, 6.476 - fingerprint, 6.477 + fingerprint->as_string(), 6.478 B->instructions_begin()); 6.479 VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end()); 6.480 Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end()); 6.481 @@ -1965,7 +2194,7 @@ 6.482 B->instructions_end()); 6.483 } 6.484 } 6.485 - return result; 6.486 + return entry; 6.487 } 6.488 6.489 void AdapterHandlerEntry::relocate(address new_base) { 6.490 @@ -2308,30 +2537,31 @@ 6.491 6.492 #ifndef PRODUCT 6.493 bool AdapterHandlerLibrary::contains(CodeBlob* b) { 6.494 - 6.495 - if (_handlers == NULL) return false; 6.496 - 6.497 - for (int i = 0 ; i < _handlers->length() ; i++) { 6.498 - AdapterHandlerEntry* a = get_entry(i); 6.499 - if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) return true; 6.500 + AdapterHandlerTableIterator iter(_adapters); 6.501 + while (iter.has_next()) { 6.502 + AdapterHandlerEntry* a = iter.next(); 6.503 + if ( b == CodeCache::find_blob(a->get_i2c_entry()) ) return true; 6.504 } 6.505 return false; 6.506 } 6.507 6.508 void AdapterHandlerLibrary::print_handler(CodeBlob* b) { 6.509 - 6.510 - for (int i = 0 ; i < _handlers->length() ; i++) { 6.511 - AdapterHandlerEntry* a = get_entry(i); 6.512 - if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) { 6.513 + AdapterHandlerTableIterator iter(_adapters); 6.514 + while (iter.has_next()) { 6.515 + AdapterHandlerEntry* a = iter.next(); 6.516 + if ( b == CodeCache::find_blob(a->get_i2c_entry()) ) { 6.517 tty->print("Adapter for signature: "); 6.518 - // Fingerprinter::print(_fingerprints->at(i)); 6.519 - tty->print("0x%" FORMAT64_MODIFIER "x", _fingerprints->at(i)); 6.520 - tty->print_cr(" i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT, 6.521 + tty->print_cr("%s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT, 6.522 + a->fingerprint()->as_string(), 6.523 a->get_i2c_entry(), a->get_c2i_entry(), a->get_c2i_unverified_entry()); 6.524 - 6.525 return; 6.526 } 6.527 } 6.528 assert(false, "Should have found handler"); 6.529 } 6.530 + 6.531 +void AdapterHandlerLibrary::print_statistics() { 6.532 + _adapters->print_statistics(); 6.533 +} 6.534 + 6.535 #endif /* PRODUCT */
7.1 --- a/src/share/vm/runtime/sharedRuntime.hpp Wed Jan 20 12:54:25 2010 -0800 7.2 +++ b/src/share/vm/runtime/sharedRuntime.hpp Wed Jan 20 22:10:33 2010 -0800 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 7.6 + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -23,6 +23,8 @@ 7.11 */ 7.12 7.13 class AdapterHandlerEntry; 7.14 +class AdapterHandlerTable; 7.15 +class AdapterFingerPrint; 7.16 class vframeStream; 7.17 7.18 // Runtime is the base class for various runtime interfaces 7.19 @@ -337,7 +339,8 @@ 7.20 int total_args_passed, 7.21 int max_arg, 7.22 const BasicType *sig_bt, 7.23 - const VMRegPair *regs); 7.24 + const VMRegPair *regs, 7.25 + AdapterFingerPrint* fingerprint); 7.26 7.27 // OSR support 7.28 7.29 @@ -528,28 +531,41 @@ 7.30 // used by the adapters. The code generation happens here because it's very 7.31 // similar to what the adapters have to do. 7.32 7.33 -class AdapterHandlerEntry : public CHeapObj { 7.34 +class AdapterHandlerEntry : public BasicHashtableEntry { 7.35 + friend class AdapterHandlerTable; 7.36 + 7.37 private: 7.38 + AdapterFingerPrint* _fingerprint; 7.39 address _i2c_entry; 7.40 address _c2i_entry; 7.41 address _c2i_unverified_entry; 7.42 7.43 + void init(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) { 7.44 + _fingerprint = fingerprint; 7.45 + _i2c_entry = i2c_entry; 7.46 + _c2i_entry = c2i_entry; 7.47 + _c2i_unverified_entry = c2i_unverified_entry; 7.48 + } 7.49 + 7.50 + // should never be used 7.51 + AdapterHandlerEntry(); 7.52 + 7.53 public: 7.54 - 7.55 // The name we give all buffer blobs 7.56 static const char* name; 7.57 7.58 - AdapterHandlerEntry(address i2c_entry, address c2i_entry, address c2i_unverified_entry): 7.59 - _i2c_entry(i2c_entry), 7.60 - _c2i_entry(c2i_entry), 7.61 - _c2i_unverified_entry(c2i_unverified_entry) { 7.62 - } 7.63 - 7.64 address get_i2c_entry() { return _i2c_entry; } 7.65 address get_c2i_entry() { return _c2i_entry; } 7.66 address get_c2i_unverified_entry() { return _c2i_unverified_entry; } 7.67 7.68 void relocate(address new_base); 7.69 + 7.70 + AdapterFingerPrint* fingerprint() { return _fingerprint; } 7.71 + 7.72 + AdapterHandlerEntry* next() { 7.73 + return (AdapterHandlerEntry*)BasicHashtableEntry::next(); 7.74 + } 7.75 + 7.76 #ifndef PRODUCT 7.77 void print(); 7.78 #endif /* PRODUCT */ 7.79 @@ -558,30 +574,18 @@ 7.80 class AdapterHandlerLibrary: public AllStatic { 7.81 private: 7.82 static BufferBlob* _buffer; // the temporary code buffer in CodeCache 7.83 - static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection 7.84 - static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers 7.85 - enum { 7.86 - AbstractMethodHandler = 1 // special handler for abstract methods 7.87 - }; 7.88 + static AdapterHandlerTable* _adapters; 7.89 + static AdapterHandlerEntry* _abstract_method_handler; 7.90 static BufferBlob* buffer_blob(); 7.91 static void initialize(); 7.92 - static int get_create_adapter_index(methodHandle method); 7.93 - static address get_i2c_entry( int index ) { 7.94 - return get_entry(index)->get_i2c_entry(); 7.95 - } 7.96 - static address get_c2i_entry( int index ) { 7.97 - return get_entry(index)->get_c2i_entry(); 7.98 - } 7.99 - static address get_c2i_unverified_entry( int index ) { 7.100 - return get_entry(index)->get_c2i_unverified_entry(); 7.101 - } 7.102 7.103 public: 7.104 - static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); } 7.105 + 7.106 + static AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, 7.107 + address i2c_entry, address c2i_entry, address c2i_unverified_entry); 7.108 static nmethod* create_native_wrapper(methodHandle method); 7.109 - static AdapterHandlerEntry* get_adapter(methodHandle method) { 7.110 - return get_entry(get_create_adapter_index(method)); 7.111 - } 7.112 + static AdapterHandlerEntry* get_adapter(methodHandle method); 7.113 + 7.114 #ifdef HAVE_DTRACE_H 7.115 static nmethod* create_dtrace_nmethod (methodHandle method); 7.116 #endif // HAVE_DTRACE_H 7.117 @@ -589,6 +593,7 @@ 7.118 #ifndef PRODUCT 7.119 static void print_handler(CodeBlob* b); 7.120 static bool contains(CodeBlob* b); 7.121 + static void print_statistics(); 7.122 #endif /* PRODUCT */ 7.123 7.124 };