]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: keep a set of all code_blocks in the code_heap
authorJoe Groff <arcata@gmail.com>
Thu, 17 Nov 2011 22:29:01 +0000 (14:29 -0800)
committerJoe Groff <arcata@gmail.com>
Wed, 23 Nov 2011 19:11:26 +0000 (11:11 -0800)
This way looking up code blocks by return address is an O(log n) set lookup rather than an O(n) linear scan.

vm/code_blocks.cpp
vm/code_heap.cpp
vm/code_heap.hpp
vm/compaction.cpp

index 6c9a2fc28419b39821b6357e86f3937d847b0da4..b636777a672b4f7540878d4a9fa7fcea2d6eaf74 100755 (executable)
@@ -436,6 +436,7 @@ code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell lab
        method returns, except when compiling words with the non-optimizing
        compiler at the beginning of bootstrap */
        this->code->uninitialized_blocks.insert(std::make_pair(compiled,literals.value()));
+       this->code->all_blocks.insert(compiled);
 
        /* next time we do a minor GC, we have to trace this code block, since
        the fields of the code_block struct might point into nursery or aging */
index f46891f7b8268164f0de1a331df12f2e267469b8..a804ee23a78f260eb61445ee96f6b34ff1c1dbd8 100755 (executable)
@@ -63,6 +63,7 @@ void code_heap::free(code_block *compiled)
        assert(!uninitialized_p(compiled));
        points_to_nursery.erase(compiled);
        points_to_aging.erase(compiled);
+       all_blocks.erase(compiled);
        allocator->free(compiled);
 }
 
@@ -71,29 +72,32 @@ void code_heap::flush_icache()
        factor::flush_icache(seg->start,seg->size);
 }
 
-struct address_finder {
-       cell address;
-       code_block *found_code_block;
-
-       address_finder(cell address)
-               : address(address), found_code_block(NULL) {}
+code_block *code_heap::code_block_for_address(cell address)
+{
+       std::set<code_block*>::const_iterator blocki =
+               all_blocks.upper_bound((code_block*)address);
+       assert(blocki != all_blocks.begin());
+       --blocki;
+       code_block* found_block = *blocki;
+       assert((cell)found_block->entry_point() <= address
+               && address - (cell)found_block->entry_point() < found_block->size());
+       return found_block;
+}
 
-       void operator()(code_block *block, cell size)
+void code_heap::update_all_blocks_map(mark_bits<code_block> *code_forwarding_map)
+{
+       std::cout << "updating block map" << std::endl;
+       std::set<code_block *> new_all_blocks;
+       for (std::set<code_block *>::const_iterator oldi = all_blocks.begin();
+               oldi != all_blocks.end();
+               ++oldi)
        {
-               if ((cell)block->entry_point() <= address
-                       && address - (cell)block->entry_point() < block->size())
-               {
-                       assert(found_code_block == NULL);
-                       found_code_block = block;
-               }
+               code_block *new_block = code_forwarding_map->forward_block(*oldi);
+               std::cout << "compact " << (void*)*oldi << " -> " << (void*)new_block << std::endl;
+               new_all_blocks.insert(new_block);
        }
-};
-
-code_block *code_heap::code_block_for_address(cell address)
-{
-       address_finder finder(address);
-       allocator->iterate(finder);
-       return finder.found_code_block;
+       std::cout << "updated" << std::endl;
+       all_blocks.swap(new_all_blocks);
 }
 
 /* Allocate a code heap during startup */
index a1a8386c25363953b30a86122b3703d9054a7167..5545f1e7d55a7c639691946445f87f725d1bcbe1 100755 (executable)
@@ -7,6 +7,8 @@ namespace factor
        const cell seh_area_size = 0;
 #endif
 
+struct compaction_fixup;
+
 struct code_heap {
        /* The actual memory area */
        segment *seg;
@@ -20,6 +22,8 @@ struct code_heap {
        /* Memory allocator */
        free_list_allocator<code_block> *allocator;
 
+       std::set<code_block *> all_blocks;
+
        /* Keys are blocks which need to be initialized by initialize_code_block().
        Values are literal tables. Literal table arrays are GC roots until the
        time the block is initialized, after which point they are discarded. */
@@ -43,6 +47,7 @@ struct code_heap {
        void flush_icache();
        void guard_safepoint();
        void unguard_safepoint();
+       void update_all_blocks_map(mark_bits<code_block> *code_forwarding_map);
 
        code_block *code_block_for_address(cell address);
 
@@ -51,6 +56,7 @@ struct code_heap {
                cell page_mask = ~(getpagesize() - 1);
                return (addr & page_mask) == (cell)safepoint_page;
        }
+
 };
 
 struct code_heap_room {
index 4c59a38886fe0f82e07066ac47d51078b885bb3b..16cc4ed92406b7e51d47ccadfa0af4b4942b70dd 100644 (file)
@@ -185,6 +185,8 @@ void factor_vm::update_code_roots_for_compaction()
                else
                        root->valid = false;
        }
+
+       code->update_all_blocks_map(state);
 }
 
 /* Compact data and code heaps */