]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/code_heap.cpp
vm: strip out call-counting profiler
[factor.git] / vm / code_heap.cpp
index ac1c0157d2265aadec51a7384539f0243c001e27..f46891f7b8268164f0de1a331df12f2e267469b8 100755 (executable)
@@ -7,8 +7,15 @@ code_heap::code_heap(cell size)
 {
        if(size > ((u64)1 << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size);
        seg = new segment(align_page(size),true);
-       if(!seg) fatal_error("Out of memory in heap allocator",size);
-       allocator = new free_list_allocator<code_block>(size,seg->start);
+       if(!seg) fatal_error("Out of memory in code_heap constructor",size);
+
+       cell start = seg->start + getpagesize() + seh_area_size;
+
+       allocator = new free_list_allocator<code_block>(seg->end - start,start);
+
+       /* See os-windows-x86.64.cpp for seh_area usage */
+       safepoint_page = (void *)seg->start;
+       seh_area = (char *)seg->start + getpagesize();
 }
 
 code_heap::~code_heap()
@@ -64,38 +71,76 @@ void code_heap::flush_icache()
        factor::flush_icache(seg->start,seg->size);
 }
 
-/* Allocate a code heap during startup */
-void factor_vm::init_code_heap(cell size)
+struct address_finder {
+       cell address;
+       code_block *found_code_block;
+
+       address_finder(cell address)
+               : address(address), found_code_block(NULL) {}
+
+       void operator()(code_block *block, cell size)
+       {
+               if ((cell)block->entry_point() <= address
+                       && address - (cell)block->entry_point() < block->size())
+               {
+                       assert(found_code_block == NULL);
+                       found_code_block = block;
+               }
+       }
+};
+
+code_block *code_heap::code_block_for_address(cell address)
 {
-       code = new code_heap(size);
+       address_finder finder(address);
+       allocator->iterate(finder);
+       return finder.found_code_block;
 }
 
-bool factor_vm::in_code_heap_p(cell ptr)
+/* Allocate a code heap during startup */
+void factor_vm::init_code_heap(cell size)
 {
-       return (ptr >= code->seg->start && ptr <= code->seg->end);
+       code = new code_heap(size);
 }
 
 struct word_updater {
        factor_vm *parent;
+       bool reset_inline_caches;
 
-       explicit word_updater(factor_vm *parent_) : parent(parent_) {}
+       word_updater(factor_vm *parent_, bool reset_inline_caches_) :
+               parent(parent_), reset_inline_caches(reset_inline_caches_) {}
 
        void operator()(code_block *compiled, cell size)
        {
-               parent->update_word_references(compiled);
+               parent->update_word_references(compiled,reset_inline_caches);
        }
 };
 
-/* Update pointers to words referenced from all code blocks. Only after
-defining a new word. */
-void factor_vm::update_code_heap_words()
+/* Update pointers to words referenced from all code blocks.
+Only needed after redefining an existing word.
+If generic words were redefined, inline caches need to be reset. */
+void factor_vm::update_code_heap_words(bool reset_inline_caches)
 {
-       word_updater updater(this);
+       word_updater updater(this,reset_inline_caches);
        each_code_block(updater);
 }
 
+/* Fix up new words only.
+Fast path for compilation units that only define new words. */
+void factor_vm::initialize_code_blocks()
+{
+       std::map<code_block *, cell>::const_iterator iter = code->uninitialized_blocks.begin();
+       std::map<code_block *, cell>::const_iterator end = code->uninitialized_blocks.end();
+
+       for(; iter != end; iter++)
+               initialize_code_block(iter->first,iter->second);
+
+       code->uninitialized_blocks.clear();
+}
+
 void factor_vm::primitive_modify_code_heap()
 {
+       bool reset_inline_caches = to_boolean(ctx->pop());
+       bool update_existing_words = to_boolean(ctx->pop());
        data_root<array> alist(ctx->pop(),this);
 
        cell count = array_capacity(alist.untagged());
@@ -133,18 +178,19 @@ void factor_vm::primitive_modify_code_heap()
                                        parameters,
                                        literals);
 
-                               word->code = compiled;
+                               word->entry_point = compiled->entry_point();
                        }
                        break;
                default:
                        critical_error("Expected a quotation or an array",data.value());
                        break;
                }
-
-               update_word_xt(word.untagged());
        }
 
-       update_code_heap_words();
+       if(update_existing_words)
+               update_code_heap_words(reset_inline_caches);
+       else
+               initialize_code_blocks();
 }
 
 code_heap_room factor_vm::code_room()
@@ -181,4 +227,41 @@ void factor_vm::primitive_strip_stack_traces()
        each_code_block(stripper);
 }
 
+struct code_block_accumulator {
+       std::vector<cell> objects;
+
+       void operator()(code_block *compiled, cell size)
+       {
+               objects.push_back(compiled->owner);
+               objects.push_back(compiled->parameters);
+               objects.push_back(compiled->relocation);
+
+               objects.push_back(tag_fixnum(compiled->type()));
+               objects.push_back(tag_fixnum(compiled->size()));
+
+               /* Note: the entry point is always a multiple of the heap
+               alignment (16 bytes). We cannot allocate while iterating
+               through the code heap, so it is not possible to call
+               from_unsigned_cell() here. It is OK, however, to add it as
+               if it were a fixnum, and have library code shift it to the
+               left by 4. */
+               cell entry_point = (cell)compiled->entry_point();
+               assert((entry_point & (data_alignment - 1)) == 0);
+               assert((entry_point & TAG_MASK) == FIXNUM_TYPE);
+               objects.push_back(entry_point);
+       }
+};
+
+cell factor_vm::code_blocks()
+{
+       code_block_accumulator accum;
+       each_code_block(accum);
+       return std_vector_to_array(accum.objects);
+}
+
+void factor_vm::primitive_code_blocks()
+{
+       ctx->push(code_blocks());
+}
+
 }