]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: modify-code-heap primitive now takes a pair of parameters, update-existing? and...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 1 Feb 2010 13:49:05 +0000 (02:49 +1300)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Wed, 3 Feb 2010 10:11:28 +0000 (23:11 +1300)
14 files changed:
basis/compiler/test/test.factor
basis/compiler/tests/low-level-ir.factor
basis/stack-checker/known-words/known-words.factor
core/bootstrap/primitives.factor
core/compiler/units/units-docs.factor
core/compiler/units/units-tests.factor
core/compiler/units/units.factor
core/words/words-docs.factor
core/words/words.factor
vm/code_blocks.cpp
vm/code_heap.cpp
vm/factor.cpp
vm/profiler.cpp
vm/vm.hpp

index cc7b3822538d9713dffd44951e631243d99f40f0..0c86a244a2e0dd9639aca08939032c464ecdf211 100644 (file)
@@ -5,7 +5,7 @@ sequences vocabs words tools.test tools.test.private ;
 IN: compiler.test
 
 : decompile ( word -- )
-    dup def>> 2array 1array modify-code-heap ;
+    dup def>> 2array 1array t t modify-code-heap ;
 
 : recompile-all ( -- )
     all-words compile ;
index b6b8e1c0313b66c630d4d25bba727af22f90af8c..a2d8bf4b2b269900f564b5b4f6d58c84cb55bd1a 100644 (file)
@@ -9,7 +9,7 @@ IN: compiler.tests.low-level-ir
 : compile-cfg ( cfg -- word )
     gensym
     [ build-mr generate code>> ] dip
-    [ associate >alist modify-code-heap ] keep ;
+    [ associate >alist t t modify-code-heap ] keep ;
 
 : compile-test-cfg ( -- word )
     cfg new 0 get >>entry
index 966a273f20e37600d60f86e5c85c29fece788839..21a49beffca986bb526d84b9f5e07c01d914d531 100644 (file)
@@ -711,7 +711,7 @@ M: bad-executable summary
 
 \ dll-valid? { object } { object } define-primitive
 
-\ modify-code-heap { array } { } define-primitive
+\ modify-code-heap { array object object } { } define-primitive
 
 \ unimplemented { } { } define-primitive
 
index 9366aa49c23c7d8ada0c493ce522e84377b2a140..826da41f954033aa0bc13601a110dadfcee02d41 100644 (file)
@@ -422,7 +422,7 @@ tuple
     { "resize-byte-array" "byte-arrays" "primitive_resize_byte_array" (( n byte-array -- newbyte-array )) }
     { "<tuple-boa>" "classes.tuple.private" "primitive_tuple_boa" (( ... layout -- tuple )) }
     { "<tuple>" "classes.tuple.private" "primitive_tuple" (( layout -- tuple )) }
-    { "modify-code-heap" "compiler.units" "primitive_modify_code_heap" (( alist -- )) }
+    { "modify-code-heap" "compiler.units" "primitive_modify_code_heap" (( alist update-existing? reset-pics? -- )) }
     { "lookup-method" "generic.single.private" "primitive_lookup_method" (( object methods -- method )) }
     { "mega-cache-miss" "generic.single.private" "primitive_mega_cache_miss" (( methods index cache -- method )) }
     { "(exists?)" "io.files.private" "primitive_existsp" (( path -- ? )) }
index b6994a2b7e323bf51576443d5f1f2410bbfa51de..e4a956444540789c3b2def33eaeb5e803b59cdf0 100644 (file)
@@ -71,8 +71,8 @@ HELP: no-compilation-unit
 { $description "Throws a " { $link no-compilation-unit } " error." }
 { $error-description "Thrown when an attempt is made to define a word outside of a " { $link with-compilation-unit } " combinator." } ;
 
-HELP: modify-code-heap ( alist -- )
-{ $values { "alist" "an alist" } }
+HELP: modify-code-heap ( alist update-existing? reset-pics? -- )
+{ $values { "alist" "an alist" } { "update-existing?" "a boolean" } { "reset-pics?" "a boolean" } }
 { $description "Stores compiled code definitions in the code heap. The alist maps words to the following:"
 { $list
     { "a quotation - in this case, the quotation is compiled with the non-optimizing compiler and the word will call the quotation when executed." }
index 48c3b6891c526bec3b5177d3eeea7859a4bfa1e4..86711f4ab0a71aa721ecb876f4aaeb91edadae71 100644 (file)
@@ -7,7 +7,7 @@ IN: compiler.units.tests
 
 ! Non-optimizing compiler bugs
 [ 1 1 ] [
-    "A" <uninterned-word> [ [ [ 1 ] dip ] 2array 1array modify-code-heap ] keep
+    "A" <uninterned-word> [ [ [ 1 ] dip ] 2array 1array t t modify-code-heap ] keep
     1 swap execute
 ] unit-test
 
index 07f8494a59345efce32ae8f9cd968d01c4234f4d..11ab8ab1f28fe51ce42222b211fa237d9d7b7721 100644 (file)
@@ -62,7 +62,8 @@ HOOK: to-recompile compiler-impl ( -- words )
 
 HOOK: process-forgotten-words compiler-impl ( words -- )
 
-: compile ( words -- ) recompile modify-code-heap ;
+: compile ( words -- )
+    recompile t f modify-code-heap ;
 
 ! Non-optimizing compiler
 M: f update-call-sites
@@ -149,13 +150,20 @@ M: object always-bump-effect-counter? drop f ;
     updated-definitions dup assoc-empty?
     [ drop ] [ notify-definition-observers notify-error-observers ] if ;
 
+: update-existing? ( defs -- ? )
+    new-words get keys diff empty? not ;
+
+: reset-pics? ( -- ? )
+    outdated-generics get assoc-empty? not ;
+
 : finish-compilation-unit ( -- )
     [ ] [
         remake-generics
-        to-recompile recompile
-        update-tuples
-        process-forgotten-definitions
-        modify-code-heap
+        to-recompile [
+            recompile
+            update-tuples
+            process-forgotten-definitions
+        ] keep update-existing? reset-pics? modify-code-heap
         bump-effect-counter
         notify-observers
     ] if-bootstrapping ;
index c762ad9fc8c4ec97ea34d34d584c9f78cf1d8ff4..69933a913cb0f6e01e175c1d8a9a860553187aa6 100644 (file)
@@ -21,6 +21,7 @@ $nl
 "There are several ways of creating an uninterned word:"
 { $subsections
     <word>
+    <uninterned-word>
     gensym
     define-temp
 } ;
@@ -246,9 +247,14 @@ $low-level-note
 
 HELP: <word> ( name vocab -- word )
 { $values { "name" string } { "vocab" string } { "word" word } }
-{ $description "Allocates an uninterned word with the specified name and vocabulary, and a blank word property hashtable. User code should call " { $link gensym } " to create uninterned words and " { $link create } " to create interned words." }
+{ $description "Allocates a word with the specified name and vocabulary. User code should call " { $link <uninterned-word> } " to create uninterned words and " { $link create } " to create interned words, instead of calling this constructor directly." }
 { $notes "This word must be called from inside " { $link with-compilation-unit } "." } ;
 
+HELP: <uninterned-word> ( name -- word )
+{ $values { "name" string } { "word" word } }
+{ $description "Creates an uninterned word with the specified name,  that is not equal to any other word in the system." }
+{ $notes "Unlike " { $link create } ", this word does not have to be called from inside " { $link with-compilation-unit } "." } ;
+
 HELP: gensym
 { $values { "word" word } }
 { $description "Creates an uninterned word that is not equal to any other word in the system." }
@@ -257,7 +263,7 @@ HELP: gensym
     "( gensym )"
     }
 }
-{ $notes "Gensyms are often used as placeholder values that have no meaning of their own but must be unique. For example, the compiler uses gensyms to label sections of code." } ;
+{ $notes "Unlike " { $link create } ", this word does not have to be called from inside " { $link with-compilation-unit } "." } ;
 
 HELP: bootstrapping?
 { $var-description "Set by the library while bootstrap is in progress. Some parsing words need to behave differently during bootstrap." } ;
index 6c6e0d188b88c9c1b11da4168a13b2c9633a0385..5b057230fe8e8daaa87f1a537c4a3e12807e3b88 100644 (file)
@@ -156,7 +156,8 @@ M: word reset-word
     2dup [ hashcode ] bi@ bitxor >fixnum (word) dup new-word ;
 
 : <uninterned-word> ( name -- word )
-    f \ <uninterned-word> counter >fixnum (word) ;
+    f \ <uninterned-word> counter >fixnum (word)
+    new-words get [ dup new-word ] when ;
 
 : gensym ( -- word )
     "( gensym )" <uninterned-word> ;
index f523dac3a051b2875a6d79064a6dd3139eab306e..e002b26afcfeee0e40bf1f41128e48dbf30cd9a2 100755 (executable)
@@ -67,8 +67,13 @@ cell factor_vm::code_block_owner(code_block *compiled)
 
 struct update_word_references_relocation_visitor {
        factor_vm *parent;
+       bool reset_inline_caches;
 
-       explicit update_word_references_relocation_visitor(factor_vm *parent_) : parent(parent_) {}
+       update_word_references_relocation_visitor(
+               factor_vm *parent_,
+               bool reset_inline_caches_) :
+               parent(parent_),
+               reset_inline_caches(reset_inline_caches_) {}
 
        void operator()(instruction_operand op)
        {
@@ -85,17 +90,23 @@ struct update_word_references_relocation_visitor {
                case RT_ENTRY_POINT_PIC:
                        {
                                code_block *compiled = op.load_code_block();
-                               cell owner = parent->code_block_owner(compiled);
-                               if(to_boolean(owner))
-                                       op.store_value(parent->compute_entry_point_pic_address(owner));
+                               if(reset_inline_caches || !compiled->pic_p())
+                               {
+                                       cell owner = parent->code_block_owner(compiled);
+                                       if(to_boolean(owner))
+                                               op.store_value(parent->compute_entry_point_pic_address(owner));
+                               }
                                break;
                        }
                case RT_ENTRY_POINT_PIC_TAIL:
                        {
                                code_block *compiled = op.load_code_block();
-                               cell owner = parent->code_block_owner(compiled);
-                               if(to_boolean(owner))
-                                       op.store_value(parent->compute_entry_point_pic_tail_address(owner));
+                               if(reset_inline_caches || !compiled->pic_p())
+                               {
+                                       cell owner = parent->code_block_owner(compiled);
+                                       if(to_boolean(owner))
+                                               op.store_value(parent->compute_entry_point_pic_tail_address(owner));
+                               }
                                break;
                        }
                default:
@@ -108,7 +119,7 @@ struct update_word_references_relocation_visitor {
 dlsyms, and words. For all other words in the code heap, we only need
 to update references to other words, without worrying about literals
 or dlsyms. */
-void factor_vm::update_word_references(code_block *compiled)
+void factor_vm::update_word_references(code_block *compiled, bool reset_inline_caches)
 {
        if(code->uninitialized_p(compiled))
                initialize_code_block(compiled);
@@ -119,11 +130,11 @@ void factor_vm::update_word_references(code_block *compiled)
           are referenced after this is done. So instead of polluting
           the code heap with dead PICs that will be freed on the next
           GC, we add them to the free list immediately. */
-       else if(compiled->pic_p())
+       else if(reset_inline_caches && compiled->pic_p())
                code->free(compiled);
        else
        {
-               update_word_references_relocation_visitor visitor(this);
+               update_word_references_relocation_visitor visitor(this,reset_inline_caches);
                compiled->each_instruction_operand(visitor);
                compiled->flush_icache();
        }
@@ -272,22 +283,25 @@ struct initial_code_block_visitor {
 };
 
 /* Perform all fixups on a code block */
-void factor_vm::initialize_code_block(code_block *compiled)
+void factor_vm::initialize_code_block(code_block *compiled, cell literals)
 {
-       std::map<code_block *,cell>::iterator iter = code->uninitialized_blocks.find(compiled);
-
-       initial_code_block_visitor visitor(this,iter->second);
+       initial_code_block_visitor visitor(this,literals);
        compiled->each_instruction_operand(visitor);
        compiled->flush_icache();
 
-       code->uninitialized_blocks.erase(iter);
-
        /* next time we do a minor GC, we have to trace this code block, since
        the newly-installed instruction operands might point to literals in
        nursery or aging */
        code->write_barrier(compiled);
 }
 
+void factor_vm::initialize_code_block(code_block *compiled)
+{
+       std::map<code_block *,cell>::iterator iter = code->uninitialized_blocks.find(compiled);
+       initialize_code_block(compiled,iter->second);
+       code->uninitialized_blocks.erase(iter);
+}
+
 /* Fixup labels. This is done at compile time, not image load time */
 void factor_vm::fixup_labels(array *labels, code_block *compiled)
 {
index b0435bb11f9ebd016d9b35c8b9575452fed01446..495b167f111adfe7b5409351c0dae1f2e3a52ce2 100755 (executable)
@@ -77,25 +77,43 @@ bool factor_vm::in_code_heap_p(cell ptr)
 
 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());
@@ -144,7 +162,10 @@ void factor_vm::primitive_modify_code_heap()
                update_word_entry_point(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()
index d5a1d2f30eae229ea618c3d31f179e36aae5f66f..fb14336ae41ffd8266a7cf963ead858fc1b62e49 100755 (executable)
@@ -81,7 +81,7 @@ void factor_vm::prepare_boot_image()
        fflush(stdout);
 
        compile_all_words();
-       update_code_heap_words();
+       update_code_heap_words(true);
        initialize_all_quotations();
        special_objects[OBJ_STAGE2] = true_object;
 
index fea78692eac3e91f70f7c372503beba87a240b6c..ef717e0fc6ea059991d39685681fe3c1a5fc88bf 100755 (executable)
@@ -55,7 +55,7 @@ void factor_vm::set_profiling(bool profiling)
                update_word_entry_point(word.untagged());
        }
 
-       update_code_heap_words();
+       update_code_heap_words(false);
 }
 
 void factor_vm::primitive_profiling()
index 6b12cc42c0f96c75aa7cdb153f3e9ab5167dc38d..f352f8833d395e9d080a6559d83eb7acc14cd1d7 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -508,12 +508,13 @@ struct factor_vm
        cell compute_entry_point_pic_address(cell w_);
        cell compute_entry_point_pic_tail_address(cell w_);
        cell code_block_owner(code_block *compiled);
-       void update_word_references(code_block *compiled);
+       void update_word_references(code_block *compiled, bool reset_inline_caches);
        void undefined_symbol();
        cell compute_dlsym_address(array *literals, cell index);
        cell compute_vm_address(cell arg);
        void store_external_address(instruction_operand op);
        cell compute_here_address(cell arg, cell offset, code_block *compiled);
+       void initialize_code_block(code_block *compiled, cell literals);
        void initialize_code_block(code_block *compiled);
        void fixup_labels(array *labels, code_block *compiled);
        code_block *allot_code_block(cell size, code_block_type type);
@@ -529,7 +530,8 @@ struct factor_vm
 
        void init_code_heap(cell size);
        bool in_code_heap_p(cell ptr);
-       void update_code_heap_words();
+       void update_code_heap_words(bool reset_inline_caches);
+       void initialize_code_blocks();
        void primitive_modify_code_heap();
        code_heap_room code_room();
        void primitive_code_room();