// Allocates memory inline object* factor_vm::allot_object(cell type, cell size) { FACTOR_ASSERT(!current_gc); bump_allocator *nursery = data->nursery; // If the object is bigger than the nursery, allocate it in tenured space if (size >= nursery->size) return allot_large_object(type, size); // If the object is smaller than the nursery, allocate it in the nursery, // after a GC if needed if (nursery->here + size > nursery->end) primitive_minor_gc(); object* obj = nursery->allot(size); obj->initialize(type); return obj; }
// 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(); }
/* Allocates memory */ inline object* factor_vm::allot_object(cell type, cell size) { FACTOR_ASSERT(!current_gc); bump_allocator *nursery = data->nursery; /* If the object is smaller than the nursery, allocate it in the nursery, after a GC if needed */ if (nursery->size > size) { /* If there is insufficient room, collect the nursery */ if (nursery->here + size > nursery->end) primitive_minor_gc(); object* obj = nursery->allot(size); obj->initialize(type); return obj; } /* If the object is bigger than the nursery, allocate it in tenured space */ else return allot_large_object(type, size); }
void factor_vm::inline_gc(cell *data_roots_base, cell data_roots_size) { data_roots.push_back(data_root_range(data_roots_base,data_roots_size)); primitive_minor_gc(); data_roots.pop_back(); }