Index: src/mark_sweep/free_area_pool.cpp =================================================================== --- src/mark_sweep/free_area_pool.cpp (revision 0) +++ src/mark_sweep/free_area_pool.cpp (revision 0) @@ -0,0 +1,67 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Ji Qi, 2006/10/05 + */ + +#include "free_area_pool.h" + +void free_area_pool_init(Free_Area_Pool* pool) +{ + for(unsigned int i = 0; i < NUM_FREE_LIST; i ++){ + Bidir_List* list = &pool->sized_area_list[i]; + list->next = list->prev = list; + } + + memset((void*)pool->list_bit_flag, 0, NUM_FLAG_WORDS << BIT_SHIFT_TO_BYTES_PER_WORD); + pool->free_pool_lock = 0; + return; +} + +void free_area_pool_reset(Free_Area_Pool* pool) +{ + free_area_pool_init(pool); +} + +Free_Area* free_pool_find_size_area(Free_Area_Pool* pool, unsigned int size) +{ + assert(size >= GC_OBJ_SIZE_THRESHOLD); + + size = ALIGN_UP_TO_KILO(size); + unsigned int index = pool_list_index_with_size(size); + /* Get first list index that is not empty */ + index = pool_list_get_next_flag(pool, index); + assert(index <= NUM_FREE_LIST); + + /*No free area left*/ + if(index == NUM_FREE_LIST) + return NULL; + + Bidir_List* list = &pool->sized_area_list[index]; + Free_Area* area = (Free_Area*)list->next; + + if(index != MAX_LIST_INDEX) + return area; + + /* Else, for last bucket MAX_LIST_INDEX, we must traverse it */ + while( area != (Free_Area*)list ){ + if(area->size >= size) return area; + area = (Free_Area*)(area->next); + } + + return NULL; +} Index: src/mark_sweep/free_area_pool.h =================================================================== --- src/mark_sweep/free_area_pool.h (revision 0) +++ src/mark_sweep/free_area_pool.h (revision 0) @@ -0,0 +1,119 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Ji Qi, 2006/10/05 + */ + +#ifndef _BUDDY_H_ +#define _BUDDY_H_ + +#include "../common/gc_common.h" +#include "../utils/bit_ops.h" +#include "../utils/bidir_list.h" + +#define ADDRESS_IS_KB_ALIGNED(addr) (!(((unsigned int)addr) & ((1 << BIT_SHIFT_TO_KILO)-1))) +#define ALIGN_UP_TO_KILO(addr) (((unsigned int)(addr) + (KB - 1)) & (~(KB- 1))) +#define ALIGN_DOWN_TO_KILO(addr) ((unsigned int)(addr) & (~(KB- 1))) + +#define NUM_FREE_LIST 128 + +typedef struct Free_Area{ + /* <-- First couple of fields overloadded as Bidir_List */ + Bidir_List* next; + Bidir_List* prev; + /* END of Bidir_List --> */ + unsigned int size; +}Free_Area; + +/* this is the only interface for new area creation */ +inline Free_Area* free_area_new(void* start, unsigned int size) +{ + assert(ADDRESS_IS_KB_ALIGNED(start)); + assert(ADDRESS_IS_KB_ALIGNED(size)); + + if( size < GC_OBJ_SIZE_THRESHOLD) return NULL; + Free_Area* area = (Free_Area*)start; + memset(area, 0, size); + area->size = size; + return area; +} + +#define NUM_FLAG_WORDS (NUM_FREE_LIST >> BIT_SHIFT_TO_BITS_PER_WORD) + +typedef struct Free_Area_Pool{ + Bidir_List sized_area_list[NUM_FREE_LIST]; + /* each list corresponds to one bit in below vector */ + unsigned int list_bit_flag[NUM_FLAG_WORDS]; + volatile unsigned int free_pool_lock; +}Free_Area_Pool; + +#define MAX_LIST_INDEX (NUM_FREE_LIST - 1) + +inline void pool_list_set_flag(Free_Area_Pool* pool, unsigned int index) +{ + words_set_bit(pool->list_bit_flag, NUM_FLAG_WORDS, index); +} + +inline void pool_list_clear_flag(Free_Area_Pool* pool, unsigned int index) +{ + words_clear_bit(pool->list_bit_flag, NUM_FLAG_WORDS, index); +} + +inline unsigned int pool_list_get_next_flag(Free_Area_Pool* pool, unsigned int start_idx) +{ + return words_get_next_set_lsb(pool->list_bit_flag, NUM_FLAG_WORDS, start_idx); +} + +inline unsigned int pool_list_index_with_size(unsigned int size) +{ + assert(size >= GC_OBJ_SIZE_THRESHOLD); + + unsigned int index; + index = size >> BIT_SHIFT_TO_KILO; + if(index > MAX_LIST_INDEX) index = MAX_LIST_INDEX; + return index; +} + +inline Free_Area* free_pool_add_area(Free_Area_Pool* pool, Free_Area* free_area) +{ + assert( free_area->size >= GC_OBJ_SIZE_THRESHOLD); + + unsigned int index = pool_list_index_with_size(free_area->size); + bidir_list_add_item(&(pool->sized_area_list[index]), (Bidir_List*)free_area); + + /* set bit flag of the list */ + pool_list_set_flag(pool, index); + return free_area; +} + +inline void free_pool_remove_area(Free_Area_Pool* pool, Free_Area* free_area) +{ + unsigned int index = pool_list_index_with_size(free_area->size); + bidir_list_remove_item((Bidir_List*)free_area); + + /* set bit flag of the list */ + Bidir_List* list = &(pool->sized_area_list[index]); + if(list->next == list){ + pool_list_clear_flag(pool, index); + } +} + +void free_area_pool_init(Free_Area_Pool* p_buddy); +void free_area_pool_reset(Free_Area_Pool* p_buddy); +Free_Area* free_pool_find_size_area(Free_Area_Pool* pool, unsigned int size); + +#endif /*ifdef _BUDDY_H_*/ Index: src/mark_sweep/lspace.cpp =================================================================== --- src/mark_sweep/lspace.cpp (revision 483341) +++ src/mark_sweep/lspace.cpp (working copy) @@ -15,76 +15,50 @@ */ /** - * @author Xiao-Feng Li, 2006/10/05 + * @author Ji Qi, 2006/10/05 */ #include "lspace.h" void* los_boundary = NULL; struct GC_Gen; -Space* gc_get_los(GC_Gen* gc); void gc_set_los(GC_Gen* gc, Space* lspace); -void* lspace_alloc(unsigned int size, Allocator *allocator) -{ - Lspace* lspace = (Lspace*)gc_get_los((GC_Gen*)allocator->gc); - - unsigned int old_free = (unsigned int)lspace->alloc_free; - unsigned int new_free = old_free + size; - while(new_free <= (unsigned int)lspace->heap_end){ - unsigned int temp = atomic_cas32((volatile unsigned int *)&lspace->alloc_free, new_free, old_free); - if (temp != old_free) { - old_free = (unsigned int)lspace->alloc_free; - new_free = old_free + size; - continue; - } - /* successfully allocate an object */ - Partial_Reveal_Object* p_return_object = (Partial_Reveal_Object*)old_free; - lspace->alloc_free = (void*)new_free; - - /* TODO: should moved to better location */ - memset(p_return_object, 0, size); - - return (void*)old_free; - } - - /* FIXME:: trigger collection */ - assert(0); - return NULL; - -} - void lspace_initialize(GC* gc, void* start, unsigned int lspace_size) { Lspace* lspace = (Lspace*)STD_MALLOC( sizeof(Lspace)); assert(lspace); memset(lspace, 0, sizeof(Lspace)); - + void* reserved_base = start; unsigned int committed_size = lspace_size; int status = port_vmem_commit(&reserved_base, committed_size, gc->allocated_memory); assert(status == APR_SUCCESS && reserved_base == start); - + memset(reserved_base, 0, committed_size); lspace->committed_heap_size = committed_size; lspace->reserved_heap_size = lspace_size - committed_size; lspace->heap_start = reserved_base; lspace->heap_end = (void *)((unsigned int)reserved_base + committed_size); - lspace->alloc_free = reserved_base; - - unsigned int num_bits = (lspace_size >> BIT_SHIFT_TO_KILO) + 1; - unsigned int num_words = (num_bits >> BIT_SHIFT_TO_BITS_PER_WORD)+1; + + /*Treat with mark bit table*/ + unsigned int num_words = LSPACE_SIZE_TO_MARKTABLE_SIZE_WORDS(lspace_size); lspace->mark_table = (unsigned int*)STD_MALLOC( num_words*BYTES_PER_WORD ); memset(lspace->mark_table, 0, num_words*BYTES_PER_WORD); - lspace->mark_object_func = lspace_mark_object; - lspace->move_object = FALSE; lspace->gc = gc; + + /*Treat with free area buddies*/ + lspace->free_pool = (Free_Area_Pool*)STD_MALLOC(sizeof(Free_Area_Pool)); + free_area_pool_init(lspace->free_pool); + Free_Area* initial_fa = (Free_Area*)lspace->heap_start; + initial_fa->size = lspace->committed_heap_size; + free_pool_add_area(lspace->free_pool, initial_fa); + gc_set_los((GC_Gen*)gc, (Space*)lspace); - los_boundary = lspace->heap_end; - + return; } @@ -97,40 +71,40 @@ return; } -void lspace_collection(Lspace* lspace) -{ - /* FIXME:: collection */ - unsigned int used_size = (unsigned int)lspace->alloc_free - (unsigned int)lspace->heap_start; - memset(lspace->mark_table, 0, (((used_size>>BIT_SHIFT_TO_KILO) + 1)>>BIT_SHIFT_TO_BITS_PER_BYTE) + 1); - - return; -} - -void reset_lspace_after_copy_nursery(Lspace* lspace) -{ - unsigned int used_size = (unsigned int)lspace->alloc_free - (unsigned int)lspace->heap_start; - memset(lspace->mark_table, 0, (used_size>>BIT_SHIFT_TO_KILO)>>BIT_SHIFT_TO_BITS_PER_BYTE ); - return; -} - - Boolean lspace_mark_object(Lspace* lspace, Partial_Reveal_Object* p_obj) { assert( obj_belongs_to_space(p_obj, (Space*)lspace)); unsigned int word_index = OBJECT_WORD_INDEX_TO_LSPACE_MARKBIT_TABLE(lspace, p_obj); unsigned int bit_offset_in_word = OBJECT_WORD_OFFSET_IN_LSPACE_MARKBIT_TABLE(lspace, p_obj); - + unsigned int* p_word = &(lspace->mark_table[word_index]); unsigned int word_mask = (1<committed_heap_size); + memset(lspace->mark_table, 0, marktable_size); + return; +} + +void lspace_collection(Lspace* lspace) +{ + /* heap is marked already, we need only sweep here. */ + lspace_sweep(lspace); + unsigned int marktable_size = LSPACE_SIZE_TO_MARKTABLE_SIZE_BYTES(lspace->committed_heap_size); + memset(lspace->mark_table, 0, marktable_size); + return; +} Index: src/mark_sweep/lspace.h =================================================================== --- src/mark_sweep/lspace.h (revision 483341) +++ src/mark_sweep/lspace.h (working copy) @@ -15,7 +15,7 @@ */ /** - * @author Xiao-Feng Li, 2006/10/05 + * @author Ji Qi, 2006/10/05 */ #ifndef _LSPACE_H_ @@ -23,6 +23,7 @@ #include "../common/gc_common.h" #include "../thread/gc_thread.h" +#include "free_area_pool.h" typedef struct Lspace{ /* <-- first couple of fields are overloadded as Space */ @@ -36,8 +37,9 @@ Boolean (*mark_object_func)(Lspace* space, Partial_Reveal_Object* p_obj); /* END of Space --> */ - void* alloc_free; - +// void* alloc_free; + Free_Area_Pool* free_pool; + unsigned int* mark_table; }Lspace; @@ -45,10 +47,16 @@ void lspace_initialize(GC* gc, void* reserved_base, unsigned int lspace_size); void lspace_destruct(Lspace* lspace); Managed_Object_Handle lspace_alloc(unsigned int size, Allocator* allocator); +void lspace_sweep(Lspace* lspace); void lspace_collection(Lspace* lspace); inline unsigned int lspace_free_memory_size(Lspace* lspace){ /* FIXME:: */ return 0; } + +#define LSPACE_SIZE_TO_MARKTABLE_SIZE_BITS(space_size) (((space_size) >> BIT_SHIFT_TO_KILO)+1) +#define LSPACE_SIZE_TO_MARKTABLE_SIZE_BYTES(space_size) ((LSPACE_SIZE_TO_MARKTABLE_SIZE_BITS(space_size)>> BIT_SHIFT_TO_BITS_PER_BYTE)+1) +#define LSPACE_SIZE_TO_MARKTABLE_SIZE_WORDS(space_size) ((LSPACE_SIZE_TO_MARKTABLE_SIZE_BYTES(space_size)>> BIT_SHIFT_TO_BYTES_PER_WORD)+1) + /* The assumption is the offset below is always aligned at word size, because both numbers are aligned */ #define ADDRESS_OFFSET_IN_LSPACE_BODY(lspace, p_obj) ((unsigned int)p_obj - (unsigned int)space_heap_start((Space*)lspace)) #define OBJECT_BIT_INDEX_TO_LSPACE_MARKBIT_TABLE(lspace, p_obj) (ADDRESS_OFFSET_IN_LSPACE_BODY(lspace, p_obj) >> BIT_SHIFT_TO_KILO) @@ -65,9 +73,62 @@ return markbits & (1<mark_table; + unsigned int* table_end = mark_table + LSPACE_SIZE_TO_MARKTABLE_SIZE_WORDS(lspace->committed_heap_size); + + unsigned j=0; + unsigned int k=0; + while( (mark_table + j) < table_end){ + unsigned int markbits = *(mark_table+j); + if(!markbits){ j++; continue; } + while(k<32){ + if( !(markbits& (1<heap_start + kilo_bytes_index * KB); + *mark_bit_idx = kilo_bytes_index; + return p_obj; + } + j++; + k=0; + } + *mark_bit_idx = 0; + return NULL; +} + + +inline Partial_Reveal_Object* lspace_get_next_marked_object(Lspace* lspace, unsigned int* mark_bit_idx) +{ + unsigned int* mark_table = lspace->mark_table; + unsigned int* table_end = mark_table + LSPACE_SIZE_TO_MARKTABLE_SIZE_WORDS(lspace->committed_heap_size); + unsigned int bit_index = *mark_bit_idx; + + unsigned int j = bit_index >> BIT_SHIFT_TO_BITS_PER_WORD; + unsigned int k = (bit_index & BIT_MASK_TO_BITS_PER_WORD) + 1; + + while( (mark_table + j) < table_end){ + unsigned int markbits = *(mark_table+j); + if(!markbits){ j++; continue; } + while(k<32){ + if( !(markbits& (1<heap_start + kilo_byte_index * KB); + *mark_bit_idx = kilo_byte_index; + return p_obj; + } + j++; + k=0; + } + + *mark_bit_idx = 0; + return NULL; + +} + Boolean lspace_mark_object(Lspace* lspace, Partial_Reveal_Object* p_obj); -void lspace_save_reloc(Lspace* space, Partial_Reveal_Object** p_ref); -void lspace_update_reloc(Lspace* lspace); void reset_lspace_after_copy_nursery(Lspace* lspace); Index: src/mark_sweep/lspace_alloc_collect.cpp =================================================================== --- src/mark_sweep/lspace_alloc_collect.cpp (revision 0) +++ src/mark_sweep/lspace_alloc_collect.cpp (revision 0) @@ -0,0 +1,111 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Ji Qi, 2006/10/05 + */ + +#include "lspace.h" +struct GC_Gen; +Space* gc_get_los(GC_Gen* gc); + +void* lspace_alloc(unsigned int size, Allocator *allocator) +{ + vm_gc_lock_enum(); + unsigned int try_count = 0; + Lspace* lspace = (Lspace*)gc_get_los((GC_Gen*)allocator->gc); + Free_Area_Pool* pool = lspace->free_pool; + Free_Area* free_area; + Free_Area* remain_area; + void* p_return = NULL; + + while( try_count < 2 ){ + free_area = free_pool_find_size_area(pool, size); + + /*Got one free area!*/ + if(free_area != NULL){ + assert(free_area->size >= size); + free_pool_remove_area(pool, free_area); + p_return = (void*)free_area; + unsigned int old_size = free_area->size; + memset(p_return, 0, sizeof(Free_Area)); + + /* we need put the remaining area back if it size is ok.*/ + void* new_start = (Free_Area*)ALIGN_UP_TO_KILO(((unsigned int)free_area + size)); + unsigned int alloc_size = (unsigned int)new_start - (unsigned int)free_area; + unsigned int new_size = old_size - alloc_size; + + remain_area = free_area_new(new_start, new_size); + if( remain_area ) + free_pool_add_area(pool, remain_area); + + vm_gc_unlock_enum(); + return p_return; + } + + if(try_count++ == 0) + gc_reclaim_heap(allocator->gc, GC_CAUSE_LOS_IS_FULL); + + } + + vm_gc_unlock_enum(); + return NULL; +} + +void lspace_sweep(Lspace* lspace) +{ + /* reset the pool first because its info is useless now. */ + free_area_pool_reset(lspace->free_pool); + + unsigned int mark_bit_idx, cur_size; + void *cur_area_start, *cur_area_end; + + + + Partial_Reveal_Object* p_prev_obj = (Partial_Reveal_Object *)lspace->heap_start; + Partial_Reveal_Object* p_next_obj = lspace_get_first_marked_object(lspace, &mark_bit_idx); + + cur_area_start = (void*)ALIGN_UP_TO_KILO(p_prev_obj); + cur_area_end = (void*)ALIGN_DOWN_TO_KILO(p_next_obj); + + + while(cur_area_end){ + cur_size = (unsigned int)cur_area_end - (unsigned int)cur_area_start; + + Free_Area* cur_area = free_area_new(cur_area_start, cur_size); + /* successfully create an area */ + if( cur_area ) + free_pool_add_area(lspace->free_pool, cur_area); + + p_prev_obj = p_next_obj; + p_next_obj = lspace_get_next_marked_object(lspace, &mark_bit_idx); + + cur_area_start = (void*)ALIGN_UP_TO_KILO((unsigned int)p_prev_obj + vm_object_size(p_prev_obj)); + cur_area_end = (void*)ALIGN_DOWN_TO_KILO(p_next_obj); + + } + + /* cur_area_end == NULL */ + cur_area_end = (void*)ALIGN_DOWN_TO_KILO(lspace->heap_end); + cur_size = (unsigned int)cur_area_end - (unsigned int)cur_area_start; + Free_Area* cur_area = free_area_new(cur_area_start, cur_size); + /* successfully create an area */ + if( cur_area ) + free_pool_add_area(lspace->free_pool, cur_area); + + return; + +} Index: src/thread/collector_alloc.cpp =================================================================== --- src/thread/collector_alloc.cpp (revision 483341) +++ src/thread/collector_alloc.cpp (working copy) @@ -32,25 +32,26 @@ assert(!obj_is_marked_in_vt(p_obj)); return NULL; } - /* otherwise, get the obj size firstly. The work below will destroy its vtable. */ + + /* otherwise, try to alloc it. mos should always has enough space to hold nos during collection */ unsigned int size = vm_object_size(p_obj); + Partial_Reveal_Object* p_targ_obj = (Partial_Reveal_Object*)mos_alloc(size, (Allocator*)collector); + assert(p_targ_obj); /* else, take the obj by setting the forwarding flag atomically we don't put a simple bit in vt because we need compute obj size later. */ - if ((unsigned int)vt != atomic_cas32((unsigned int*)obj_get_vtraw_addr(p_obj), ((unsigned int)FORWARDING_BIT_MASK), (unsigned int)vt)) { - /* forwarded by other */ + if ((unsigned int)vt != atomic_cas32((unsigned int*)obj_get_vtraw_addr(p_obj), ((unsigned int)p_targ_obj|FORWARDING_BIT_MASK), (unsigned int)vt)) { + /* forwarded by other, we need unalloc the allocated obj. We may waste some space if the allocation switched + block. The remaining part of the switched block cannot be revivied for next allocation of + object that has smaller size than this one. */ assert( obj_is_forwarded_in_vt(p_obj) && !obj_is_marked_in_vt(p_obj)); + thread_local_unalloc(size, (Allocator*)collector); return NULL; } - /* we hold the object, now forward it */ - Partial_Reveal_Object* p_targ_obj = (Partial_Reveal_Object*)mos_alloc(size, (Allocator*)collector); - /* mos should always has enough space to hold nos during collection */ - assert(p_targ_obj); + /* we forwarded the object */ memcpy(p_targ_obj, p_obj, size); - - /* because p_obj has forwarding flag in its vt, we set it here */ - obj_set_forwarding_pointer_in_vt(p_obj, p_targ_obj); + /* because p_obj has forwarding pointer in its vt, we set it seperately here */ obj_set_vt(p_targ_obj, (Allocation_Handle)vt); return p_targ_obj; Index: src/thread/gc_thread.h =================================================================== --- src/thread/gc_thread.h (revision 483341) +++ src/thread/gc_thread.h (working copy) @@ -48,6 +48,13 @@ VmThreadHandle thread_handle; /* This thread; */ }Allocator; +inline void thread_local_unalloc(unsigned int size, Allocator* allocator) +{ + void* free = allocator->free; + allocator->free = (void*)((unsigned int)free - size); + return; +} + inline Partial_Reveal_Object* thread_local_alloc(unsigned int size, Allocator* allocator) { void* free = allocator->free; Index: src/trace_forward/fspace_collect_forward.cpp =================================================================== --- src/trace_forward/fspace_collect_forward.cpp (revision 483341) +++ src/trace_forward/fspace_collect_forward.cpp (working copy) @@ -122,11 +122,7 @@ is set in the atomic instruction, which requires to roll back the mos_alloced space. That is easy for thread local block allocation cancellation. */ if( p_target_obj == NULL ){ - Partial_Reveal_Object *forward_ptr = obj_get_forwarding_pointer_in_vt(p_obj); - while(forward_ptr == NULL) - forward_ptr = obj_get_forwarding_pointer_in_vt(p_obj); - - *p_ref = forward_ptr; + *p_ref = obj_get_forwarding_pointer_in_vt(p_obj); return; } /* otherwise, we successfully forwarded */ Index: src/utils/bidir_list.h =================================================================== --- src/utils/bidir_list.h (revision 0) +++ src/utils/bidir_list.h (revision 0) @@ -0,0 +1,46 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Ji Qi, 2006/10/05 + */ + +#ifndef _BIDIR_LIST_H_ +#define _BIDIR_LIST_H_ + +typedef struct Bidir_List{ + Bidir_List* next; + Bidir_List* prev; +}Bidir_List; + +inline Bidir_List* bidir_list_add_item(Bidir_List* head, Bidir_List* item) +{ + item->next = head; + item->prev = head->prev; + head->prev->next = item; + head->prev = item; + return head; +} + +inline Bidir_List* bidir_list_remove_item(Bidir_List* item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; + item->next = item->prev = item; + return item; +} + +#endif /* _BIDIR_LIST_H_ */ Index: src/utils/bit_ops.h =================================================================== --- src/utils/bit_ops.h (revision 0) +++ src/utils/bit_ops.h (revision 0) @@ -0,0 +1,117 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Ji, Qi, 2006/10/25 + */ + +#ifndef _BIT_OPS_H_ +#define _BIT_OPS_H_ + +#include "../common/gc_common.h" + +inline unsigned int word_get_first_set_lsb(unsigned int target_word) +{ + assert(target_word != 0); + unsigned int bit_offset; + +#ifdef _EM64T_ + +#else /* ifdef _EM64T_*/ +#ifdef PLATFORM_POSIX /* POSIX Platform*/ + __asm__ __volatile__( + "bsf %1,%0\n" + :"=r"(bit_offset) + :"m"(target_word) + ); +#else /*WIN32 Platform*/ + __asm{ + bsf eax, target_word + mov bit_offset, eax + } +#endif /* ifdef PLATFORM_POSIX else*/ +#endif /* ifdef _EM64T_ else */ + return bit_offset; + +} + +inline unsigned int words_get_next_set_lsb(unsigned int* words, unsigned int count, unsigned int start_idx) +{ + unsigned int bit_offset; + + assert((start_idx >= 0) && (start_idx < 128)); + + unsigned int start_word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD; + unsigned int start_bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD; + + bit_offset = start_idx - start_bit_offset; + for(unsigned int i = start_word_index; i < count; i ++ ){ + unsigned int cur_word = *(words + i); + + if(start_word_index == i){ + unsigned int mask = ~((1 << start_bit_offset) - 1); + cur_word = cur_word & mask; + } + + if(cur_word != 0){ + bit_offset += word_get_first_set_lsb(cur_word); + return bit_offset; + } + + bit_offset += 32; + } + + return bit_offset; +} + +inline void words_set_bit(unsigned int* words, unsigned int count, unsigned int start_idx) +{ + assert((start_idx >= 0) && (start_idx < 128)); + + unsigned int word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD; + unsigned int bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD; + + if(word_index >= count) return; + + unsigned int* p_word = words + word_index; + unsigned int old_value = *p_word; + unsigned int mask = 1 << bit_offset; + unsigned int new_value = old_value|mask; + + *p_word = new_value; + + return; +} + +inline void words_clear_bit(unsigned int* words, unsigned int count, unsigned int start_idx) +{ + assert((start_idx >= 0) && (start_idx < 128)); + + unsigned int word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD; + unsigned int bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD; + + if(word_index >= count) return; + + unsigned int* p_word = words + word_index; + unsigned int old_value = *p_word; + unsigned int mask = ~(1 << bit_offset); + unsigned int new_value = old_value & mask; + + *p_word = new_value; + + return; +} +#endif