/* classes.tuple uses this to reshape tuples; tools.deploy.shaker uses this to coalesce equal but distinct quotations and wrappers. */ void factor_vm::primitive_become() { array *new_objects = untag_check<array>(ctx->pop()); array *old_objects = untag_check<array>(ctx->pop()); cell capacity = array_capacity(new_objects); if(capacity != array_capacity(old_objects)) critical_error("bad parameters to become",0); /* Build the forwarding map */ std::map<object *,object *> become_map; for(cell i = 0; i < capacity; i++) { tagged<object> old_obj(array_nth(old_objects,i)); tagged<object> new_obj(array_nth(new_objects,i)); if(old_obj != new_obj) become_map[old_obj.untagged()] = new_obj.untagged(); } /* Update all references to old objects to point to new objects */ { slot_visitor<slot_become_fixup> workhorse(this,slot_become_fixup(&become_map)); workhorse.visit_roots(); workhorse.visit_contexts(); object_become_visitor object_visitor(&workhorse); each_object(object_visitor); code_block_become_visitor code_block_visitor(&workhorse); each_code_block(code_block_visitor); } /* Since we may have introduced old->new references, need to revisit all objects and code blocks on a minor GC. */ data->mark_all_cards(); { code_block_write_barrier_visitor code_block_visitor(code); each_code_block(code_block_visitor); } }
// classes.tuple uses this to reshape tuples; tools.deploy.shaker uses this // to coalesce equal but distinct quotations and wrappers. // Calls gc void factor_vm::primitive_become() { primitive_minor_gc(); array* new_objects = untag_check<array>(ctx->pop()); array* old_objects = untag_check<array>(ctx->pop()); cell capacity = array_capacity(new_objects); if (capacity != array_capacity(old_objects)) critical_error("bad parameters to become", 0); // Build the forwarding map std::map<object*, object*> become_map; for (cell i = 0; i < capacity; i++) { cell old_ptr = array_nth(old_objects, i); cell new_ptr = array_nth(new_objects, i); if (old_ptr != new_ptr) become_map[untag<object>(old_ptr)] = untag<object>(new_ptr); } // Update all references to old objects to point to new objects { slot_visitor<slot_become_fixup> visitor(this, slot_become_fixup(&become_map)); visitor.visit_all_roots(); auto object_become_func = [&](object* obj) { visitor.visit_slots(obj); }; each_object(object_become_func); auto code_block_become_func = [&](code_block* compiled, cell size) { visitor.visit_code_block_objects(compiled); visitor.visit_embedded_literals(compiled); code->write_barrier(compiled); }; each_code_block(code_block_become_func); } // Since we may have introduced old->new references, need to revisit // all objects and code blocks on a minor GC. data->mark_all_cards(); }
/* 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) { auto word_updater = [&](code_block* block, cell size) { update_word_references(block, reset_inline_caches); }; each_code_block(word_updater); }
/* 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,reset_inline_caches); each_code_block(updater); }
cell factor_vm::code_blocks() { code_block_accumulator accum; each_code_block(accum); return std_vector_to_array(accum.objects); }
void factor_vm::primitive_strip_stack_traces() { stack_trace_stripper stripper; each_code_block(stripper); }