hotspot/src/share/vm/oops/instanceKlass.cpp
changeset 225 6258c2e3adfd
parent 217 c646ef2f5d58
parent 222 3d1795325749
child 360 21d113ecbf6a
equal deleted inserted replaced
219:ac2d788217ca 225:6258c2e3adfd
   970 
   970 
   971     // Do all the safepointing things (allocations) before grabbing the lock.
   971     // Do all the safepointing things (allocations) before grabbing the lock.
   972     // These allocations will have to be freed if they are unused.
   972     // These allocations will have to be freed if they are unused.
   973 
   973 
   974     // Allocate a new array of methods.
   974     // Allocate a new array of methods.
   975     jmethodID* to_dealloc_jmeths = NULL;
       
   976     jmethodID* new_jmeths = NULL;
   975     jmethodID* new_jmeths = NULL;
   977     if (length <= idnum) {
   976     if (length <= idnum) {
   978       // A new array will be needed (unless some other thread beats us to it)
   977       // A new array will be needed (unless some other thread beats us to it)
   979       size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count());
   978       size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count());
   980       new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1);
   979       new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1);
   981       memset(new_jmeths, 0, (size+1)*sizeof(jmethodID));
   980       memset(new_jmeths, 0, (size+1)*sizeof(jmethodID));
   982       new_jmeths[0] =(jmethodID)size;  // array size held in the first element
   981       new_jmeths[0] =(jmethodID)size;  // array size held in the first element
   983     }
   982     }
   984 
   983 
   985     // Allocate a new method ID.
   984     // Allocate a new method ID.
   986     jmethodID to_dealloc_id = NULL;
       
   987     jmethodID new_id = NULL;
   985     jmethodID new_id = NULL;
   988     if (method_h->is_old() && !method_h->is_obsolete()) {
   986     if (method_h->is_old() && !method_h->is_obsolete()) {
   989       // The method passed in is old (but not obsolete), we need to use the current version
   987       // The method passed in is old (but not obsolete), we need to use the current version
   990       methodOop current_method = ik_h->method_with_idnum((int)idnum);
   988       methodOop current_method = ik_h->method_with_idnum((int)idnum);
   991       assert(current_method != NULL, "old and but not obsolete, so should exist");
   989       assert(current_method != NULL, "old and but not obsolete, so should exist");
   995       // It is the current version of the method or an obsolete method,
   993       // It is the current version of the method or an obsolete method,
   996       // use the version passed in
   994       // use the version passed in
   997       new_id = JNIHandles::make_jmethod_id(method_h);
   995       new_id = JNIHandles::make_jmethod_id(method_h);
   998     }
   996     }
   999 
   997 
  1000     {
   998     if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
       
   999       // No need and unsafe to lock the JmethodIdCreation_lock at safepoint.
       
  1000       id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
       
  1001     } else {
  1001       MutexLocker ml(JmethodIdCreation_lock);
  1002       MutexLocker ml(JmethodIdCreation_lock);
  1002 
  1003       id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
  1003       // We must not go to a safepoint while holding this lock.
  1004     }
  1004       debug_only(No_Safepoint_Verifier nosafepoints;)
  1005   }
  1005 
  1006   return id;
  1006       // Retry lookup after we got the lock
  1007 }
  1007       jmeths = ik_h->methods_jmethod_ids_acquire();
  1008 
  1008       if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
  1009 
  1009         if (jmeths != NULL) {
  1010 jmethodID instanceKlass::get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
  1010           // We have grown the array: copy the existing entries, and delete the old array
  1011                                         jmethodID new_id, jmethodID* new_jmeths) {
  1011           for (size_t index = 0; index < length; index++) {
  1012   // Retry lookup after we got the lock or ensured we are at safepoint
  1012             new_jmeths[index+1] = jmeths[index+1];
  1013   jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
  1013           }
  1014   jmethodID  id                = NULL;
  1014           to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
  1015   jmethodID  to_dealloc_id     = NULL;
  1015         }
  1016   jmethodID* to_dealloc_jmeths = NULL;
  1016         ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
  1017   size_t     length;
  1017       } else {
  1018 
  1018         id = jmeths[idnum+1];
  1019   if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
  1019         to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
  1020     if (jmeths != NULL) {
  1020       }
  1021       // We have grown the array: copy the existing entries, and delete the old array
  1021       if (id == NULL) {
  1022       for (size_t index = 0; index < length; index++) {
  1022         id = new_id;
  1023         new_jmeths[index+1] = jmeths[index+1];
  1023         jmeths[idnum+1] = id;  // install the new method ID
  1024       }
  1024       } else {
  1025       to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
  1025         to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
  1026     }
  1026       }
  1027     ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
  1027     }
  1028   } else {
  1028 
  1029     id = jmeths[idnum+1];
  1029     // Free up unneeded or no longer needed resources
  1030     to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
  1030     FreeHeap(to_dealloc_jmeths);
  1031   }
  1031     if (to_dealloc_id != NULL) {
  1032   if (id == NULL) {
  1032       JNIHandles::destroy_jmethod_id(to_dealloc_id);
  1033     id = new_id;
  1033     }
  1034     jmeths[idnum+1] = id;  // install the new method ID
       
  1035   } else {
       
  1036     to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
       
  1037   }
       
  1038 
       
  1039   // Free up unneeded or no longer needed resources
       
  1040   FreeHeap(to_dealloc_jmeths);
       
  1041   if (to_dealloc_id != NULL) {
       
  1042     JNIHandles::destroy_jmethod_id(to_dealloc_id);
  1034   }
  1043   }
  1035   return id;
  1044   return id;
  1036 }
  1045 }
  1037 
  1046 
  1038 
  1047 
  2185 
  2194 
  2186   // RC_TRACE macro has an embedded ResourceMark
  2195   // RC_TRACE macro has an embedded ResourceMark
  2187   RC_TRACE(0x00000100, ("adding previous version ref for %s @%d, EMCP_cnt=%d",
  2196   RC_TRACE(0x00000100, ("adding previous version ref for %s @%d, EMCP_cnt=%d",
  2188     ikh->external_name(), _previous_versions->length(), emcp_method_count));
  2197     ikh->external_name(), _previous_versions->length(), emcp_method_count));
  2189   constantPoolHandle cp_h(ikh->constants());
  2198   constantPoolHandle cp_h(ikh->constants());
  2190   jweak cp_ref = JNIHandles::make_weak_global(cp_h);
  2199   jobject cp_ref;
       
  2200   if (cp_h->is_shared()) {
       
  2201     // a shared ConstantPool requires a regular reference; a weak
       
  2202     // reference would be collectible
       
  2203     cp_ref = JNIHandles::make_global(cp_h);
       
  2204   } else {
       
  2205     cp_ref = JNIHandles::make_weak_global(cp_h);
       
  2206   }
  2191   PreviousVersionNode * pv_node = NULL;
  2207   PreviousVersionNode * pv_node = NULL;
  2192   objArrayOop old_methods = ikh->methods();
  2208   objArrayOop old_methods = ikh->methods();
  2193 
  2209 
  2194   if (emcp_method_count == 0) {
  2210   if (emcp_method_count == 0) {
  2195     pv_node = new PreviousVersionNode(cp_ref, NULL);
  2211     // non-shared ConstantPool gets a weak reference
       
  2212     pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), NULL);
  2196     RC_TRACE(0x00000400,
  2213     RC_TRACE(0x00000400,
  2197       ("add: all methods are obsolete; flushing any EMCP weak refs"));
  2214       ("add: all methods are obsolete; flushing any EMCP weak refs"));
  2198   } else {
  2215   } else {
  2199     int local_count = 0;
  2216     int local_count = 0;
  2200     GrowableArray<jweak>* method_refs = new (ResourceObj::C_HEAP)
  2217     GrowableArray<jweak>* method_refs = new (ResourceObj::C_HEAP)
  2210           // no more EMCP methods so bail out now
  2227           // no more EMCP methods so bail out now
  2211           break;
  2228           break;
  2212         }
  2229         }
  2213       }
  2230       }
  2214     }
  2231     }
  2215     pv_node = new PreviousVersionNode(cp_ref, method_refs);
  2232     // non-shared ConstantPool gets a weak reference
       
  2233     pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), method_refs);
  2216   }
  2234   }
  2217 
  2235 
  2218   _previous_versions->append(pv_node);
  2236   _previous_versions->append(pv_node);
  2219 
  2237 
  2220   // Using weak references allows the interesting parts of previous
  2238   // Using weak references allows the interesting parts of previous
  2228   // skip the last entry since we just added it
  2246   // skip the last entry since we just added it
  2229   for (int i = _previous_versions->length() - 2; i >= 0; i--) {
  2247   for (int i = _previous_versions->length() - 2; i >= 0; i--) {
  2230     // check the previous versions array for a GC'ed weak refs
  2248     // check the previous versions array for a GC'ed weak refs
  2231     pv_node = _previous_versions->at(i);
  2249     pv_node = _previous_versions->at(i);
  2232     cp_ref = pv_node->prev_constant_pool();
  2250     cp_ref = pv_node->prev_constant_pool();
  2233     assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
  2251     assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
  2234     if (cp_ref == NULL) {
  2252     if (cp_ref == NULL) {
  2235       delete pv_node;
  2253       delete pv_node;
  2236       _previous_versions->remove_at(i);
  2254       _previous_versions->remove_at(i);
  2237       // Since we are traversing the array backwards, we don't have to
  2255       // Since we are traversing the array backwards, we don't have to
  2238       // do anything special with the index.
  2256       // do anything special with the index.
  2301         // skip the last entry since we just added it
  2319         // skip the last entry since we just added it
  2302         for (int j = _previous_versions->length() - 2; j >= 0; j--) {
  2320         for (int j = _previous_versions->length() - 2; j >= 0; j--) {
  2303           // check the previous versions array for a GC'ed weak refs
  2321           // check the previous versions array for a GC'ed weak refs
  2304           pv_node = _previous_versions->at(j);
  2322           pv_node = _previous_versions->at(j);
  2305           cp_ref = pv_node->prev_constant_pool();
  2323           cp_ref = pv_node->prev_constant_pool();
  2306           assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
  2324           assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
  2307           if (cp_ref == NULL) {
  2325           if (cp_ref == NULL) {
  2308             delete pv_node;
  2326             delete pv_node;
  2309             _previous_versions->remove_at(j);
  2327             _previous_versions->remove_at(j);
  2310             // Since we are traversing the array backwards, we don't have to
  2328             // Since we are traversing the array backwards, we don't have to
  2311             // do anything special with the index.
  2329             // do anything special with the index.
  2399   for (int i = _previous_versions->length() - 1; i >= 0; i--) {
  2417   for (int i = _previous_versions->length() - 1; i >= 0; i--) {
  2400     // Check the previous versions array for an info node that hasn't
  2418     // Check the previous versions array for an info node that hasn't
  2401     // been GC'ed
  2419     // been GC'ed
  2402     PreviousVersionNode * pv_node = _previous_versions->at(i);
  2420     PreviousVersionNode * pv_node = _previous_versions->at(i);
  2403 
  2421 
  2404     jweak cp_ref = pv_node->prev_constant_pool();
  2422     jobject cp_ref = pv_node->prev_constant_pool();
  2405     assert(cp_ref != NULL, "weak reference was unexpectedly cleared");
  2423     assert(cp_ref != NULL, "cp reference was unexpectedly cleared");
  2406     if (cp_ref == NULL) {
  2424     if (cp_ref == NULL) {
  2407       continue;  // robustness
  2425       continue;  // robustness
  2408     }
  2426     }
  2409 
  2427 
  2410     constantPoolOop cp = (constantPoolOop)JNIHandles::resolve(cp_ref);
  2428     constantPoolOop cp = (constantPoolOop)JNIHandles::resolve(cp_ref);
  2460   } // if no array and idnum isn't included there is nothing to do
  2478   } // if no array and idnum isn't included there is nothing to do
  2461 }
  2479 }
  2462 
  2480 
  2463 // Construct a PreviousVersionNode entry for the array hung off
  2481 // Construct a PreviousVersionNode entry for the array hung off
  2464 // the instanceKlass.
  2482 // the instanceKlass.
  2465 PreviousVersionNode::PreviousVersionNode(jweak prev_constant_pool,
  2483 PreviousVersionNode::PreviousVersionNode(jobject prev_constant_pool,
  2466   GrowableArray<jweak>* prev_EMCP_methods) {
  2484   bool prev_cp_is_weak, GrowableArray<jweak>* prev_EMCP_methods) {
  2467 
  2485 
  2468   _prev_constant_pool = prev_constant_pool;
  2486   _prev_constant_pool = prev_constant_pool;
       
  2487   _prev_cp_is_weak = prev_cp_is_weak;
  2469   _prev_EMCP_methods = prev_EMCP_methods;
  2488   _prev_EMCP_methods = prev_EMCP_methods;
  2470 }
  2489 }
  2471 
  2490 
  2472 
  2491 
  2473 // Destroy a PreviousVersionNode
  2492 // Destroy a PreviousVersionNode
  2474 PreviousVersionNode::~PreviousVersionNode() {
  2493 PreviousVersionNode::~PreviousVersionNode() {
  2475   if (_prev_constant_pool != NULL) {
  2494   if (_prev_constant_pool != NULL) {
  2476     JNIHandles::destroy_weak_global(_prev_constant_pool);
  2495     if (_prev_cp_is_weak) {
       
  2496       JNIHandles::destroy_weak_global(_prev_constant_pool);
       
  2497     } else {
       
  2498       JNIHandles::destroy_global(_prev_constant_pool);
       
  2499     }
  2477   }
  2500   }
  2478 
  2501 
  2479   if (_prev_EMCP_methods != NULL) {
  2502   if (_prev_EMCP_methods != NULL) {
  2480     for (int i = _prev_EMCP_methods->length() - 1; i >= 0; i--) {
  2503     for (int i = _prev_EMCP_methods->length() - 1; i >= 0; i--) {
  2481       jweak method_ref = _prev_EMCP_methods->at(i);
  2504       jweak method_ref = _prev_EMCP_methods->at(i);
  2491 // Construct a PreviousVersionInfo entry
  2514 // Construct a PreviousVersionInfo entry
  2492 PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) {
  2515 PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) {
  2493   _prev_constant_pool_handle = constantPoolHandle();  // NULL handle
  2516   _prev_constant_pool_handle = constantPoolHandle();  // NULL handle
  2494   _prev_EMCP_method_handles = NULL;
  2517   _prev_EMCP_method_handles = NULL;
  2495 
  2518 
  2496   jweak cp_ref = pv_node->prev_constant_pool();
  2519   jobject cp_ref = pv_node->prev_constant_pool();
  2497   assert(cp_ref != NULL, "weak constant pool ref was unexpectedly cleared");
  2520   assert(cp_ref != NULL, "constant pool ref was unexpectedly cleared");
  2498   if (cp_ref == NULL) {
  2521   if (cp_ref == NULL) {
  2499     return;  // robustness
  2522     return;  // robustness
  2500   }
  2523   }
  2501 
  2524 
  2502   constantPoolOop cp = (constantPoolOop)JNIHandles::resolve(cp_ref);
  2525   constantPoolOop cp = (constantPoolOop)JNIHandles::resolve(cp_ref);