23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "classfile/altHashing.hpp" |
26 #include "classfile/altHashing.hpp" |
27 #include "classfile/javaClasses.hpp" |
27 #include "classfile/javaClasses.hpp" |
28 #include "code/dependencies.hpp" |
|
29 #include "memory/allocation.inline.hpp" |
28 #include "memory/allocation.inline.hpp" |
30 #include "memory/filemap.hpp" |
29 #include "memory/filemap.hpp" |
31 #include "memory/resourceArea.hpp" |
30 #include "memory/resourceArea.hpp" |
32 #include "oops/oop.inline.hpp" |
31 #include "oops/oop.inline.hpp" |
33 #include "runtime/safepoint.hpp" |
32 #include "runtime/safepoint.hpp" |
351 } |
350 } |
352 |
351 |
353 #endif |
352 #endif |
354 |
353 |
355 |
354 |
356 template<class T, class M> GenericHashtable<T, M>::GenericHashtable(int size, bool C_heap, MEMFLAGS memflag) { |
|
357 assert(size > 0, " Invalid hashtable size"); |
|
358 _size = size; |
|
359 _C_heap = C_heap; |
|
360 _memflag = memflag; |
|
361 // Perform subtype-specific resource allocation |
|
362 _items = (C_heap) ? NEW_C_HEAP_ARRAY(T*, size, memflag) : NEW_RESOURCE_ARRAY(T*, size); |
|
363 memset(_items, 0, sizeof(T*) * size); |
|
364 |
|
365 DEBUG_ONLY(_num_items = 0;) |
|
366 } |
|
367 |
|
368 template<class T, class M> GenericHashtable<T, M>::~GenericHashtable() { |
|
369 if (on_C_heap()) { |
|
370 // Check backing array |
|
371 for (int i = 0; i < size(); i++) { |
|
372 T* item = head(i); |
|
373 // Delete all items in linked list |
|
374 while (item != NULL) { |
|
375 T* next_item = item->next(); |
|
376 delete item; |
|
377 DEBUG_ONLY(_num_items--); |
|
378 item = next_item; |
|
379 } |
|
380 } |
|
381 FREE_C_HEAP_ARRAY(T*, _items, _memflag); |
|
382 _items = NULL; |
|
383 assert (_num_items == 0, "Not all memory released"); |
|
384 } |
|
385 } |
|
386 |
|
387 /** |
|
388 * Return a pointer to the item 'I' that is stored in the hashtable for |
|
389 * which match_item->equals(I) == true. If no such item is found, NULL |
|
390 * is returned. |
|
391 */ |
|
392 template<class T, class F> T* GenericHashtable<T, F>::contains(T* match_item) { |
|
393 if (match_item != NULL) { |
|
394 int idx = index(match_item); |
|
395 return contains_impl(match_item, idx); |
|
396 } |
|
397 return NULL; |
|
398 } |
|
399 |
|
400 /** |
|
401 * Add item to the hashtable. Return 'true' if the item was added |
|
402 * and false otherwise. |
|
403 */ |
|
404 template<class T, class F> bool GenericHashtable<T, F>::add(T* item) { |
|
405 if (item != NULL) { |
|
406 int idx = index(item); |
|
407 T* found_item = contains_impl(item, idx); |
|
408 if (found_item == NULL) { |
|
409 T* list_head = head(idx); |
|
410 item->set_next(list_head); |
|
411 item->set_prev(NULL); |
|
412 |
|
413 if (list_head != NULL) { |
|
414 list_head->set_prev(item); |
|
415 } |
|
416 set_head(item, idx); |
|
417 DEBUG_ONLY(_num_items++); |
|
418 return true; |
|
419 } |
|
420 } |
|
421 return false; |
|
422 } |
|
423 |
|
424 /** |
|
425 * Removes an item 'I' from the hashtable, if present. 'I' is removed, if |
|
426 * match_item->equals(I) == true. Removing an item from the hashtable does |
|
427 * not free memory. |
|
428 */ |
|
429 template<class T, class F> T* GenericHashtable<T, F>::remove(T* match_item) { |
|
430 if (match_item != NULL) { |
|
431 int idx = index(match_item); |
|
432 T* found_item = contains_impl(match_item, idx); |
|
433 if (found_item != NULL) { |
|
434 // Remove item from linked list |
|
435 T* prev = found_item->prev(); |
|
436 T* next = found_item->next(); |
|
437 if (prev != NULL) { |
|
438 prev->set_next(next); |
|
439 } else { |
|
440 set_head(next, idx); |
|
441 } |
|
442 if (next != NULL) { |
|
443 next->set_prev(prev); |
|
444 } |
|
445 |
|
446 DEBUG_ONLY(_num_items--); |
|
447 return found_item; |
|
448 } |
|
449 } |
|
450 return NULL; |
|
451 } |
|
452 |
|
453 |
|
454 template<class T, class F> T* GenericHashtable<T, F>::contains_impl(T* item, int idx) { |
|
455 T* current_item = head(idx); |
|
456 while (current_item != NULL) { |
|
457 if (current_item->equals(item)) { |
|
458 return current_item; |
|
459 } |
|
460 current_item = current_item->next(); |
|
461 } |
|
462 return NULL; |
|
463 } |
|
464 |
|
465 |
|
466 // Explicitly instantiate these types |
355 // Explicitly instantiate these types |
467 template class Hashtable<ConstantPool*, mtClass>; |
356 template class Hashtable<ConstantPool*, mtClass>; |
468 template class Hashtable<Symbol*, mtSymbol>; |
357 template class Hashtable<Symbol*, mtSymbol>; |
469 template class Hashtable<Klass*, mtClass>; |
358 template class Hashtable<Klass*, mtClass>; |
470 template class Hashtable<oop, mtClass>; |
359 template class Hashtable<oop, mtClass>; |