comparison src/share/vm/oops/instanceKlass.cpp @ 52:75b0f3cb1943

Merge
author dcubed
date Thu, 13 Mar 2008 14:17:48 -0700
parents 52fed2ec0afb 31000d79ec71
children ba764ed4b6f2
comparison
equal deleted inserted replaced
46:8b6e49187640 52:75b0f3cb1943
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);