00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #include "hprof.h"
00070
00071
00072
00073 #define BV_CHUNK_POWER_2 3
00074 #define BV_CHUNK_TYPE unsigned char
00075
00076 #define BV_CHUNK_BITSIZE (((int)sizeof(BV_CHUNK_TYPE))<<3)
00077 #define BV_CHUNK_INDEX_MASK ( (1 << BV_CHUNK_POWER_2) - 1 )
00078 #define BV_ELEMENT_COUNT(nelems) ((((nelems+1)) >> BV_CHUNK_POWER_2) + 1)
00079
00080 #define BV_CHUNK_ROUND(i) ((i) & ~(BV_CHUNK_INDEX_MASK))
00081 #define BV_CHUNK(ptr, i) \
00082 (((BV_CHUNK_TYPE*)(ptr))[(i) >> BV_CHUNK_POWER_2])
00083 #define BV_CHUNK_MASK(i) \
00084 (1 << ((i) & BV_CHUNK_INDEX_MASK))
00085
00086
00087
00088 typedef unsigned HashCode;
00089
00090
00091
00092 typedef struct TableKey {
00093 void *ptr;
00094 int len;
00095 } TableKey;
00096
00097
00098
00099 typedef struct TableElement {
00100 TableKey key;
00101 HashCode hcode;
00102 TableIndex next;
00103 void *info;
00104 } TableElement;
00105
00106
00107
00108 typedef struct LookupTable {
00109 char name[48];
00110 void *table;
00111 TableIndex *hash_buckets;
00112 Blocks *info_blocks;
00113 Blocks *key_blocks;
00114 TableIndex next_index;
00115 TableIndex table_size;
00116 TableIndex table_incr;
00117 TableIndex hash_bucket_count;
00118 int elem_size;
00119 int info_size;
00120 void *freed_bv;
00121 int freed_count;
00122 TableIndex freed_start;
00123 int resizes;
00124 unsigned bucket_walks;
00125 jrawMonitorID lock;
00126 SerialNumber serial_num;
00127 TableIndex hare;
00128 } LookupTable;
00129
00130
00131
00132 #define ELEMENT_PTR(ltable, i) \
00133 ((void*)(((char*)(ltable)->table) + (ltable)->elem_size * (i)))
00134
00135
00136
00137 #define SANITY_CHECK(condition) ( (condition) ? (void)0 : \
00138 HPROF_ERROR(JNI_FALSE, "SANITY IN QUESTION: " #condition))
00139
00140
00141
00142 #define SANITY_CHECK_INDEX(ltable,i) SANITY_CHECK((i) < ltable->next_index)
00143
00144
00145
00146
00147
00148
00149
00150
00151 #define _SANITY_USE_HARE
00152 #ifdef _SANITY_USE_HARE
00153 #define SANITY_ADD_HARE(i,hare) (SANITY_REMOVE_HARE(i) | (hare))
00154 #define SANITY_REMOVE_HARE(i) ((i) & 0x0FFFFFFF)
00155 #define SANITY_CHECK_HARE(i,hare) SANITY_CHECK(SANITY_ADD_HARE(i,hare)==(i))
00156 #else
00157 #define SANITY_ADD_HARE(i,hare) (i)
00158 #define SANITY_REMOVE_HARE(i) (i)
00159 #define SANITY_CHECK_HARE(i,hare)
00160 #endif
00161
00162 static jrawMonitorID
00163 lock_create(char *name)
00164 {
00165 jrawMonitorID stanley;
00166
00167 stanley = createRawMonitor(name);
00168 return stanley;
00169 }
00170
00171 static void
00172 lock_destroy(jrawMonitorID stanley)
00173 {
00174 if ( stanley != NULL ) {
00175 destroyRawMonitor(stanley);
00176 }
00177 }
00178
00179 static void
00180 lock_enter(jrawMonitorID stanley)
00181 {
00182 if ( stanley != NULL ) {
00183 rawMonitorEnter(stanley);
00184 }
00185 }
00186
00187 static void
00188 lock_exit(jrawMonitorID stanley)
00189 {
00190 if ( stanley != NULL ) {
00191 rawMonitorExit(stanley);
00192 }
00193 }
00194
00195 static void
00196 get_key(LookupTable *ltable, TableIndex index, void **pkey_ptr, int *pkey_len)
00197 {
00198 *pkey_ptr = ((TableElement*)ELEMENT_PTR(ltable,index))->key.ptr;
00199 *pkey_len = ((TableElement*)ELEMENT_PTR(ltable,index))->key.len;
00200 }
00201
00202 static void *
00203 get_info(LookupTable *ltable, TableIndex index)
00204 {
00205 TableElement *element;
00206
00207 if ( ltable->info_size == 0 ) {
00208 return NULL;
00209 }
00210 element = (TableElement*)ELEMENT_PTR(ltable,index);
00211 return element->info;
00212 }
00213
00214 static void
00215 hash_out(LookupTable *ltable, TableIndex index)
00216 {
00217 if ( ltable->hash_bucket_count > 0 ) {
00218 TableElement *element;
00219 TableElement *prev_e;
00220 TableIndex bucket;
00221 TableIndex i;
00222
00223 element = (TableElement*)ELEMENT_PTR(ltable,index);
00224 bucket = (element->hcode % ltable->hash_bucket_count);
00225 i = ltable->hash_buckets[bucket];
00226 HPROF_ASSERT(i!=0);
00227 prev_e = NULL;
00228 while ( i != 0 && i != index ) {
00229 prev_e = (TableElement*)ELEMENT_PTR(ltable,i);
00230 i = prev_e->next;
00231 }
00232 HPROF_ASSERT(i==index);
00233 if ( prev_e == NULL ) {
00234 ltable->hash_buckets[bucket] = element->next;
00235 } else {
00236 prev_e->next = element->next;
00237 }
00238 element->next = 0;
00239 element->hcode = 0;
00240 }
00241 }
00242
00243 static jboolean
00244 is_freed_entry(LookupTable *ltable, TableIndex index)
00245 {
00246 if ( ltable->freed_bv == NULL ) {
00247 return JNI_FALSE;
00248 }
00249 if ( ( BV_CHUNK(ltable->freed_bv, index) & BV_CHUNK_MASK(index) ) != 0 ) {
00250 return JNI_TRUE;
00251 }
00252 return JNI_FALSE;
00253 }
00254
00255 static void
00256 set_freed_bit(LookupTable *ltable, TableIndex index)
00257 {
00258 void *p;
00259
00260 HPROF_ASSERT(!is_freed_entry(ltable, index));
00261 p = ltable->freed_bv;
00262 if ( p == NULL ) {
00263 int size;
00264
00265
00266 HPROF_ASSERT(ltable->freed_start==0);
00267 HPROF_ASSERT(ltable->freed_start==0);
00268 size = BV_ELEMENT_COUNT(ltable->table_size);
00269 p = HPROF_MALLOC(size*(int)sizeof(BV_CHUNK_TYPE));
00270 ltable->freed_bv = p;
00271 (void)memset(p, 0, size*(int)sizeof(BV_CHUNK_TYPE));
00272 }
00273 BV_CHUNK(p, index) |= BV_CHUNK_MASK(index);
00274 ltable->freed_count++;
00275 if ( ltable->freed_count == 1 ) {
00276
00277 HPROF_ASSERT(ltable->freed_start==0);
00278 ltable->freed_start = index;
00279 } else if ( index < ltable->freed_start ) {
00280
00281 HPROF_ASSERT(ltable->freed_start!=0);
00282 ltable->freed_start = index;
00283 }
00284 HPROF_ASSERT(ltable->freed_start!=0);
00285 HPROF_ASSERT(ltable->freed_start < ltable->next_index);
00286 HPROF_ASSERT(is_freed_entry(ltable, index));
00287 }
00288
00289 static TableIndex
00290 find_freed_entry(LookupTable *ltable)
00291 {
00292 if ( ltable->freed_count > 0 ) {
00293 TableIndex i;
00294 TableIndex istart;
00295 void *p;
00296 BV_CHUNK_TYPE chunk;
00297
00298 HPROF_ASSERT(BV_CHUNK_BITSIZE==(1<<BV_CHUNK_POWER_2));
00299
00300 p = ltable->freed_bv;
00301 HPROF_ASSERT(p!=NULL);
00302
00303
00304 HPROF_ASSERT(ltable->freed_start!=0);
00305 HPROF_ASSERT(ltable->freed_start < ltable->next_index);
00306 istart = BV_CHUNK_ROUND(ltable->freed_start);
00307
00308
00309 chunk = 0;
00310 for( ; istart < ltable->next_index ; istart += BV_CHUNK_BITSIZE ) {
00311 chunk = BV_CHUNK(p, istart);
00312 if ( chunk != 0 ) {
00313 break;
00314 }
00315 }
00316 HPROF_ASSERT(chunk!=0);
00317 HPROF_ASSERT(chunk==BV_CHUNK(p,istart));
00318 HPROF_ASSERT(istart < ltable->next_index);
00319
00320
00321 for( i = istart ; i < (istart+BV_CHUNK_BITSIZE) ; i++) {
00322 BV_CHUNK_TYPE mask;
00323
00324 mask = BV_CHUNK_MASK(i);
00325 if ( (chunk & mask) != 0 ) {
00326 HPROF_ASSERT(chunk==BV_CHUNK(p,i));
00327 chunk &= ~mask;
00328 BV_CHUNK(p, i) = chunk;
00329 ltable->freed_count--;
00330 HPROF_ASSERT(i < ltable->next_index);
00331 if ( ltable->freed_count > 0 ) {
00332
00333 HPROF_ASSERT((i+1) < ltable->next_index);
00334 ltable->freed_start = i+1;
00335 } else {
00336
00337 ltable->freed_start = 0;
00338 }
00339 HPROF_ASSERT(!is_freed_entry(ltable, i));
00340 return i;
00341 }
00342 }
00343 HPROF_ASSERT(0);
00344 }
00345 return 0;
00346 }
00347
00348 static void
00349 free_entry(LookupTable *ltable, TableIndex index)
00350 {
00351 set_freed_bit(ltable, index);
00352 hash_out(ltable, index);
00353 }
00354
00355
00356 static HashCode
00357 hashcode(void *key_ptr, int key_len)
00358 {
00359 unsigned char * p;
00360 HashCode hcode;
00361 int i;
00362
00363 hcode = 0;
00364 if ( key_ptr == NULL || key_len == 0 ) {
00365 return hcode;
00366 }
00367 i = 0;
00368 p = (unsigned char*)key_ptr;
00369 for ( ; i < key_len-3 ; i += 4 ) {
00370
00371 hcode += (
00372 ( (unsigned)(p[i]) << 24 ) |
00373 ( (unsigned)(p[i+1]) << 16 ) |
00374 ( (unsigned)(p[i+2]) << 8 ) |
00375 ( (unsigned)(p[i+3]) )
00376 );
00377 }
00378 for ( ; i < key_len ; i++ ) {
00379 hcode += (unsigned)(p[i]);
00380 }
00381 return hcode;
00382 }
00383
00384 static void
00385 hash_in(LookupTable *ltable, TableIndex index, HashCode hcode)
00386 {
00387 if ( ltable->hash_bucket_count > 0 ) {
00388 TableElement *element;
00389 TableIndex bucket;
00390
00391 bucket = (hcode % ltable->hash_bucket_count);
00392 element = (TableElement*)ELEMENT_PTR(ltable, index);
00393 element->hcode = hcode;
00394 element->next = ltable->hash_buckets[bucket];
00395 ltable->hash_buckets[bucket] = index;
00396 }
00397 }
00398
00399 static void
00400 resize_hash_buckets(LookupTable *ltable)
00401 {
00402
00403
00404
00405
00406
00407 if ( ( ltable->hash_bucket_count < (ltable->next_index >> 4) )
00408 && ( ltable->hash_bucket_count > 0 )
00409 && ( ( ltable->resizes % 10 ) == 0 )
00410 && ( ltable->bucket_walks > 1000*ltable->hash_bucket_count )
00411 ) {
00412 int old_size;
00413 int new_size;
00414 TableIndex *new_buckets;
00415 TableIndex *old_buckets;
00416 int bucket;
00417
00418
00419
00420 LOG3("Table resize", ltable->name, ltable->resizes);
00421
00422 old_size = ltable->hash_bucket_count;
00423 old_buckets = ltable->hash_buckets;
00424 new_size = (ltable->next_index >> 3);
00425 SANITY_CHECK(new_size > old_size);
00426 new_buckets = HPROF_MALLOC(new_size*(int)sizeof(TableIndex));
00427 (void)memset(new_buckets, 0, new_size*(int)sizeof(TableIndex));
00428 ltable->hash_bucket_count = new_size;
00429 ltable->hash_buckets = new_buckets;
00430
00431 for ( bucket = 0 ; bucket < old_size ; bucket++ ) {
00432 TableIndex index;
00433
00434 index = old_buckets[bucket];
00435 while ( index != 0 ) {
00436 TableElement *element;
00437 TableIndex next;
00438
00439 element = (TableElement*)ELEMENT_PTR(ltable, index);
00440 next = element->next;
00441 element->next = 0;
00442 hash_in(ltable, index, element->hcode);
00443 index = next;
00444 }
00445 }
00446 HPROF_FREE(old_buckets);
00447
00448 ltable->bucket_walks = 0;
00449 }
00450 }
00451
00452 static void
00453 resize(LookupTable *ltable)
00454 {
00455 int old_size;
00456 int new_size;
00457 void *old_table;
00458 void *new_table;
00459 int nbytes;
00460 int obytes;
00461
00462 LOG3("Table resize", ltable->name, ltable->resizes);
00463
00464
00465
00466
00467 old_size = ltable->table_size;
00468 if ( ltable->table_incr < (unsigned)(old_size >> 2) ) {
00469 ltable->table_incr = (old_size >> 2);
00470 }
00471 if ( ltable->table_incr < 512 ) {
00472 ltable->table_incr = 512;
00473 }
00474 new_size = old_size + ltable->table_incr;
00475
00476
00477 obytes = old_size * ltable->elem_size;
00478 nbytes = new_size * ltable->elem_size;
00479 old_table = ltable->table;
00480 new_table = HPROF_MALLOC(nbytes);
00481 (void)memcpy(new_table, old_table, obytes);
00482 (void)memset(((char*)new_table)+obytes, 0, nbytes-obytes);
00483 ltable->table = new_table;
00484 ltable->table_size = new_size;
00485 HPROF_FREE(old_table);
00486
00487
00488 if ( ltable->freed_bv != NULL ) {
00489 void *old_bv;
00490 void *new_bv;
00491
00492 obytes = BV_ELEMENT_COUNT(old_size)*(int)sizeof(BV_CHUNK_TYPE);
00493 nbytes = BV_ELEMENT_COUNT(new_size)*(int)sizeof(BV_CHUNK_TYPE);
00494 old_bv = ltable->freed_bv;
00495 new_bv = HPROF_MALLOC(nbytes);
00496 (void)memcpy(new_bv, old_bv, obytes);
00497 (void)memset(((char*)new_bv)+obytes, 0, nbytes-obytes);
00498 ltable->freed_bv = new_bv;
00499 HPROF_FREE(old_bv);
00500 }
00501
00502
00503 resize_hash_buckets(ltable);
00504
00505 ltable->resizes++;
00506 }
00507
00508 static jboolean
00509 keys_equal(void *key_ptr1, void *key_ptr2, int key_len)
00510 {
00511 unsigned char * p1;
00512 unsigned char * p2;
00513 int i;
00514
00515 if ( key_len == 0 ) {
00516 return JNI_TRUE;
00517 }
00518
00519
00520
00521
00522 p1 = (unsigned char*)key_ptr1;
00523 p2 = (unsigned char*)key_ptr2;
00524 for ( i = 0 ; i < key_len-3 ; i += 4 ) {
00525
00526 if ( *(unsigned*)(p1+i) != *(unsigned*)(p2+i) ) {
00527 return JNI_FALSE;
00528 }
00529 }
00530 for ( ; i < key_len ; i++ ) {
00531 if ( p1[i] != p2[i] ) {
00532 return JNI_FALSE;
00533 }
00534 }
00535 return JNI_TRUE;
00536 }
00537
00538 static TableIndex
00539 find_entry(LookupTable *ltable, void *key_ptr, int key_len, HashCode hcode)
00540 {
00541 TableIndex index;
00542
00543 HPROF_ASSERT(ltable!=NULL);
00544
00545 index = 0;
00546 if ( ltable->hash_bucket_count > 0 ) {
00547 TableIndex bucket;
00548 TableIndex prev_index;
00549
00550 HPROF_ASSERT(key_ptr!=NULL);
00551 HPROF_ASSERT(key_len>0);
00552 prev_index = 0;
00553 bucket = (hcode % ltable->hash_bucket_count);
00554 index = ltable->hash_buckets[bucket];
00555 while ( index != 0 ) {
00556 TableElement *element;
00557 TableElement *prev_element;
00558
00559 element = (TableElement*)ELEMENT_PTR(ltable, index);
00560 if ( hcode == element->hcode &&
00561 key_len == element->key.len &&
00562 keys_equal(key_ptr, element->key.ptr, key_len) ) {
00563
00564 if ( prev_index != 0 ) {
00565 prev_element = (TableElement*)ELEMENT_PTR(ltable, prev_index);
00566 prev_element->next = element->next;
00567 element->next = ltable->hash_buckets[bucket];
00568 ltable->hash_buckets[bucket] = index;
00569 }
00570 break;
00571 }
00572 prev_index = index;
00573 index = element->next;
00574 ltable->bucket_walks++;
00575 }
00576 }
00577 return index;
00578 }
00579
00580 static TableIndex
00581 setup_new_entry(LookupTable *ltable, void *key_ptr, int key_len, void *info_ptr)
00582 {
00583 TableIndex index;
00584 TableElement *element;
00585 void *info;
00586 void *dup_key;
00587
00588
00589 dup_key = NULL;
00590 info = NULL;
00591
00592
00593 index = 0;
00594 if ( ltable->freed_count > 0 ) {
00595 index = find_freed_entry(ltable);
00596 }
00597 if ( index != 0 ) {
00598 int old_key_len;
00599
00600
00601 element = (TableElement*)ELEMENT_PTR(ltable, index);
00602 dup_key = element->key.ptr;
00603 old_key_len = element->key.len;
00604 info = element->info;
00605 (void)memset(element, 0, ltable->elem_size);
00606
00607
00608 if ( key_ptr != NULL ) {
00609 if ( old_key_len < key_len ) {
00610
00611
00612
00613 dup_key = NULL;
00614 }
00615 }
00616 } else {
00617
00618
00619 if ( ltable->next_index >= ltable->table_size ) {
00620 resize(ltable);
00621 }
00622 index = ltable->next_index++;
00623 element = (TableElement*)ELEMENT_PTR(ltable, index);
00624 }
00625
00626
00627 if ( ltable->info_size > 0 ) {
00628 if ( info == NULL ) {
00629 info = blocks_alloc(ltable->info_blocks, ltable->info_size);
00630 }
00631 if ( info_ptr==NULL ) {
00632 (void)memset(info, 0, ltable->info_size);
00633 } else {
00634 (void)memcpy(info, info_ptr, ltable->info_size);
00635 }
00636 }
00637
00638
00639 if ( key_ptr != NULL ) {
00640 if ( dup_key == NULL ) {
00641 dup_key = blocks_alloc(ltable->key_blocks, key_len);
00642 }
00643 (void)memcpy(dup_key, key_ptr, key_len);
00644 }
00645
00646
00647 element->key.ptr = dup_key;
00648 element->key.len = key_len;
00649 element->info = info;
00650
00651 return index;
00652 }
00653
00654 LookupTable *
00655 table_initialize(const char *name, int size, int incr, int bucket_count,
00656 int info_size)
00657 {
00658 LookupTable * ltable;
00659 char lock_name[80];
00660 int elem_size;
00661 int key_size;
00662
00663 HPROF_ASSERT(name!=NULL);
00664 HPROF_ASSERT(size>0);
00665 HPROF_ASSERT(incr>0);
00666 HPROF_ASSERT(bucket_count>=0);
00667 HPROF_ASSERT(info_size>=0);
00668
00669 key_size = 1;
00670 ltable = (LookupTable *)HPROF_MALLOC((int)sizeof(LookupTable));
00671 (void)memset(ltable, 0, (int)sizeof(LookupTable));
00672
00673 (void)strncpy(ltable->name, name, sizeof(ltable->name));
00674
00675 elem_size = (int)sizeof(TableElement);
00676
00677 ltable->next_index = 1;
00678 ltable->table_size = size;
00679 ltable->table_incr = incr;
00680 ltable->hash_bucket_count = bucket_count;
00681 ltable->elem_size = elem_size;
00682 ltable->info_size = info_size;
00683 if ( info_size > 0 ) {
00684 ltable->info_blocks = blocks_init(8, info_size, incr);
00685 }
00686 if ( key_size > 0 ) {
00687 ltable->key_blocks = blocks_init(8, key_size, incr);
00688 }
00689 ltable->table = HPROF_MALLOC(size * elem_size);
00690 (void)memset(ltable->table, 0, size * elem_size);
00691 if ( bucket_count > 0 ) {
00692 int nbytes;
00693
00694 nbytes = (int)(bucket_count*sizeof(TableIndex));
00695 ltable->hash_buckets = (TableIndex*)HPROF_MALLOC(nbytes);
00696 (void)memset(ltable->hash_buckets, 0, nbytes);
00697 }
00698
00699 (void)md_snprintf(lock_name, sizeof(lock_name),
00700 "HPROF %s table lock", name);
00701 lock_name[sizeof(lock_name)-1] = 0;
00702 ltable->lock = lock_create(lock_name);
00703 ltable->serial_num = gdata->table_serial_number_counter++;
00704 ltable->hare = (ltable->serial_num << 28);
00705
00706 LOG3("Table initialized", ltable->name, ltable->table_size);
00707 return ltable;
00708 }
00709
00710 int
00711 table_element_count(LookupTable *ltable)
00712 {
00713 int nelems;
00714
00715 HPROF_ASSERT(ltable!=NULL);
00716
00717 lock_enter(ltable->lock); {
00718 nelems = ltable->next_index-1;
00719 } lock_exit(ltable->lock);
00720
00721 return nelems;
00722 }
00723
00724 void
00725 table_free_entry(LookupTable *ltable, TableIndex index)
00726 {
00727 HPROF_ASSERT(ltable!=NULL);
00728 SANITY_CHECK_HARE(index, ltable->hare);
00729 index = SANITY_REMOVE_HARE(index);
00730 SANITY_CHECK_INDEX(ltable, index);
00731
00732 lock_enter(ltable->lock); {
00733 HPROF_ASSERT(!is_freed_entry(ltable, index));
00734 free_entry(ltable, index);
00735 } lock_exit(ltable->lock);
00736 }
00737
00738 void
00739 table_walk_items(LookupTable *ltable, LookupTableIterator func, void* arg)
00740 {
00741 if ( ltable == NULL || ltable->next_index <= 1 ) {
00742 return;
00743 }
00744 HPROF_ASSERT(func!=NULL);
00745
00746 lock_enter(ltable->lock); {
00747 TableIndex index;
00748 int fcount;
00749
00750 LOG3("table_walk_items() count+free", ltable->name, ltable->next_index);
00751 fcount = 0;
00752 for ( index = 1 ; index < ltable->next_index ; index++ ) {
00753 if ( ! is_freed_entry(ltable, index) ) {
00754 void *key_ptr;
00755 int key_len;
00756 void *info;
00757
00758 get_key(ltable, index, &key_ptr, &key_len);
00759 info = get_info(ltable, index);
00760 (*func)(SANITY_ADD_HARE(index, ltable->hare), key_ptr, key_len, info, arg);
00761 if ( is_freed_entry(ltable, index) ) {
00762 fcount++;
00763 }
00764 } else {
00765 fcount++;
00766 }
00767 }
00768 LOG3("table_walk_items() count-free", ltable->name, ltable->next_index);
00769 HPROF_ASSERT(fcount==ltable->freed_count);
00770 } lock_exit(ltable->lock);
00771 }
00772
00773 void
00774 table_cleanup(LookupTable *ltable, LookupTableIterator func, void *arg)
00775 {
00776 if ( ltable == NULL ) {
00777 return;
00778 }
00779
00780 if ( func != NULL ) {
00781 table_walk_items(ltable, func, arg);
00782 }
00783
00784 lock_enter(ltable->lock); {
00785
00786 HPROF_FREE(ltable->table);
00787 if ( ltable->hash_buckets != NULL ) {
00788 HPROF_FREE(ltable->hash_buckets);
00789 }
00790 if ( ltable->freed_bv != NULL ) {
00791 HPROF_FREE(ltable->freed_bv);
00792 }
00793 if ( ltable->info_blocks != NULL ) {
00794 blocks_term(ltable->info_blocks);
00795 ltable->info_blocks = NULL;
00796 }
00797 if ( ltable->key_blocks != NULL ) {
00798 blocks_term(ltable->key_blocks);
00799 ltable->key_blocks = NULL;
00800 }
00801
00802 } lock_exit(ltable->lock);
00803
00804 lock_destroy(ltable->lock);
00805 ltable->lock = NULL;
00806
00807 HPROF_FREE(ltable);
00808 ltable = NULL;
00809 }
00810
00811 TableIndex
00812 table_create_entry(LookupTable *ltable, void *key_ptr, int key_len, void *info_ptr)
00813 {
00814 TableIndex index;
00815 HashCode hcode;
00816
00817 HPROF_ASSERT(ltable!=NULL);
00818
00819
00820 hcode = 0;
00821 if ( ltable->hash_bucket_count > 0 ) {
00822 hcode = hashcode(key_ptr, key_len);
00823 }
00824
00825
00826 lock_enter(ltable->lock); {
00827
00828
00829 index = setup_new_entry(ltable, key_ptr, key_len, info_ptr);
00830
00831
00832 if ( ltable->hash_bucket_count > 0 ) {
00833 hash_in(ltable, index, hcode);
00834 }
00835
00836 } lock_exit(ltable->lock);
00837 return SANITY_ADD_HARE(index, ltable->hare);
00838 }
00839
00840 TableIndex
00841 table_find_entry(LookupTable *ltable, void *key_ptr, int key_len)
00842 {
00843 TableIndex index;
00844 HashCode hcode;
00845
00846
00847 hcode = 0;
00848 if ( ltable->hash_bucket_count > 0 ) {
00849 hcode = hashcode(key_ptr, key_len);
00850 }
00851
00852
00853 lock_enter(ltable->lock); {
00854 index = find_entry(ltable, key_ptr, key_len, hcode);
00855 } lock_exit(ltable->lock);
00856
00857 return index==0 ? index : SANITY_ADD_HARE(index, ltable->hare);
00858 }
00859
00860 TableIndex
00861 table_find_or_create_entry(LookupTable *ltable, void *key_ptr, int key_len,
00862 jboolean *pnew_entry, void *info_ptr)
00863 {
00864 TableIndex index;
00865 HashCode hcode;
00866
00867
00868 if ( pnew_entry ) {
00869 *pnew_entry = JNI_FALSE;
00870 }
00871
00872
00873 hcode = 0;
00874 if ( ltable->hash_bucket_count > 0 ) {
00875 hcode = hashcode(key_ptr, key_len);
00876 }
00877
00878
00879 index = 0;
00880 lock_enter(ltable->lock); {
00881 if ( ltable->hash_bucket_count > 0 ) {
00882 index = find_entry(ltable, key_ptr, key_len, hcode);
00883 }
00884 if ( index == 0 ) {
00885
00886
00887 index = setup_new_entry(ltable, key_ptr, key_len, info_ptr);
00888
00889
00890 if ( ltable->hash_bucket_count > 0 ) {
00891 hash_in(ltable, index, hcode);
00892 }
00893
00894 if ( pnew_entry ) {
00895 *pnew_entry = JNI_TRUE;
00896 }
00897 }
00898 } lock_exit(ltable->lock);
00899
00900 return SANITY_ADD_HARE(index, ltable->hare);
00901 }
00902
00903 void *
00904 table_get_info(LookupTable *ltable, TableIndex index)
00905 {
00906 void *info;
00907
00908 HPROF_ASSERT(ltable!=NULL);
00909 HPROF_ASSERT(ltable->info_size > 0);
00910 SANITY_CHECK_HARE(index, ltable->hare);
00911 index = SANITY_REMOVE_HARE(index);
00912 SANITY_CHECK_INDEX(ltable, index);
00913
00914 lock_enter(ltable->lock); {
00915 HPROF_ASSERT(!is_freed_entry(ltable, index));
00916 info = get_info(ltable,index);
00917 } lock_exit(ltable->lock);
00918
00919 return info;
00920 }
00921
00922 void
00923 table_get_key(LookupTable *ltable, TableIndex index, void **pkey_ptr, int *pkey_len)
00924 {
00925 HPROF_ASSERT(ltable!=NULL);
00926 HPROF_ASSERT(pkey_ptr!=NULL);
00927 HPROF_ASSERT(pkey_len!=NULL);
00928 SANITY_CHECK_HARE(index, ltable->hare);
00929 HPROF_ASSERT(ltable->elem_size!=0);
00930 index = SANITY_REMOVE_HARE(index);
00931 SANITY_CHECK_INDEX(ltable, index);
00932
00933 lock_enter(ltable->lock); {
00934 HPROF_ASSERT(!is_freed_entry(ltable, index));
00935 get_key(ltable, index, pkey_ptr, pkey_len);
00936 } lock_exit(ltable->lock);
00937 }
00938
00939 void
00940 table_lock_enter(LookupTable *ltable)
00941 {
00942 lock_enter(ltable->lock);
00943 }
00944
00945 void
00946 table_lock_exit(LookupTable *ltable)
00947 {
00948 lock_exit(ltable->lock);
00949 }
00950