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

Wed, 20 Jan 2010 22:10:33 -0800

author
never
date
Wed, 20 Jan 2010 22:10:33 -0800
changeset 1622
cf0685d550f1
parent 1614
3d6016e040d6
child 1623
99af867dfa05

6911204: generated adapters with large signatures can fill up the code cache
Reviewed-by: kvn, jrose

src/cpu/sparc/vm/sharedRuntime_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/sharedRuntime_x86_32.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/sharedRuntime_x86_64.cpp file | annotate | diff | comparison | revisions
src/share/vm/includeDB_core file | annotate | diff | comparison | revisions
src/share/vm/oops/methodOop.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.hpp file | annotate | diff | comparison | revisions
     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  };

mercurial