diff --git a/vm/collector.hpp b/vm/collector.hpp index 2dd360f088..3058d4c74e 100644 --- a/vm/collector.hpp +++ b/vm/collector.hpp @@ -95,14 +95,13 @@ template struct collector { } void trace_partial_objects(cell start, cell card_start, cell card_end) { - object* obj = (object*)start; - cell end = start + obj->binary_payload_start(); - start += sizeof(cell); + cell *scan_start = (cell*)start + 1; + cell *scan_end = scan_start + ((object*)start)->slot_count(); - start = std::max(start, card_start); - end = std::min(end, card_end); + scan_start = std::max(scan_start, (cell*)card_start); + scan_end = std::min(scan_end, (cell*)card_end); - visitor.visit_object_array((cell*)start, (cell*)end); + visitor.visit_object_array(scan_start, scan_end); } template diff --git a/vm/layouts.hpp b/vm/layouts.hpp index 263a469dc0..eb9218ab46 100644 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -121,8 +121,8 @@ struct object { template cell size(Fixup fixup) const; cell size() const; - cell binary_payload_start() const; - template cell binary_payload_start(Fixup fixup) const; + cell slot_count() const; + template cell slot_count(Fixup fixup) const; cell* slots() const { return (cell*)this; } @@ -332,9 +332,12 @@ struct tuple : public object { cell* data() const { return (cell*)(this + 1); } }; +inline static cell tuple_capacity(const tuple_layout *layout) { + return untag_fixnum(layout->size); +} + inline static cell tuple_size(const tuple_layout* layout) { - cell size = untag_fixnum(layout->size); - return sizeof(tuple) + size * sizeof(cell); + return sizeof(tuple) + tuple_capacity(layout) * sizeof(cell); } inline static cell string_capacity(const string* str) { diff --git a/vm/objects.hpp b/vm/objects.hpp index a5994acd5c..e97877a45e 100644 --- a/vm/objects.hpp +++ b/vm/objects.hpp @@ -121,15 +121,12 @@ inline static bool save_special_p(cell i) { } template void object::each_slot(Iterator& iter) { - cell scan = (cell)this; - cell payload_start = binary_payload_start(); - cell end = scan + payload_start; + cell* start = (cell*)this + 1; + cell* end = start + slot_count(); - scan += sizeof(cell); - - while (scan < end) { - iter((cell*)scan); - scan += sizeof(cell); + while (start < end) { + iter(start); + start++; } } diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index c0b68b2af1..1d68ce5ae2 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -48,49 +48,45 @@ cell object::size(Fixup fixup) const { inline cell object::size() const { return size(no_fixup()); } -/* The number of cells from the start of the object which should be scanned by -the GC. Some types have a binary payload at the end (string, word, DLL) which -we ignore. */ -template cell object::binary_payload_start(Fixup fixup) const { +/* The number of slots (cells) in an object which should be scanned by + the GC. The number can vary in arrays and tuples, in all other + types the number is a constant. */ +template +inline cell object::slot_count(Fixup fixup) const { if (free_p()) return 0; - switch (type()) { - /* these objects do not refer to other objects at all */ - case FLOAT_TYPE: - case BYTE_ARRAY_TYPE: - case BIGNUM_TYPE: - case CALLSTACK_TYPE: - return 0; - /* these objects have some binary data at the end */ - case WORD_TYPE: - return sizeof(word) - sizeof(cell); - case ALIEN_TYPE: - return sizeof(cell) * 3; - case DLL_TYPE: - return sizeof(cell) * 2; - case QUOTATION_TYPE: - return sizeof(quotation) - sizeof(cell); - case STRING_TYPE: - return sizeof(string); - /* everything else consists entirely of pointers */ - case ARRAY_TYPE: - return array_size(array_capacity((array*)this)); - case TUPLE_TYPE: { - tuple_layout* layout = (tuple_layout*)fixup.translate_data( - untag(((tuple*)this)->layout)); - return tuple_size(layout); + cell t = type(); + if (t == ARRAY_TYPE) { + /* capacity + n slots */ + return 1 + array_capacity((array*)this); + } else if (t == TUPLE_TYPE) { + tuple_layout* layout = (tuple_layout*)fixup.translate_data( + untag(((tuple*)this)->layout)); + /* layout + n slots */ + return 1 + tuple_capacity(layout); + } else { + switch (t) { + /* these objects do not refer to other objects at all */ + case FLOAT_TYPE: + case BYTE_ARRAY_TYPE: + case BIGNUM_TYPE: + case CALLSTACK_TYPE: return 0; + case WORD_TYPE: return 8; + case ALIEN_TYPE: return 2; + case DLL_TYPE: return 1; + case QUOTATION_TYPE: return 3; + case STRING_TYPE: return 3; + case WRAPPER_TYPE: return 1; + default: + critical_error("Invalid header in slot_count", (cell)this); + return 0; /* can't happen */ } - case WRAPPER_TYPE: - return sizeof(wrapper); - default: - critical_error("Invalid header in binary_payload_start", (cell)this); - return 0; /* can't happen */ } } -inline cell object::binary_payload_start() const { - return binary_payload_start(no_fixup()); +inline cell object::slot_count() const { + return slot_count(no_fixup()); } /* Slot visitors iterate over the slots of an object, applying a functor to @@ -130,7 +126,6 @@ template struct slot_visitor { cell visit_pointer(cell pointer); void visit_handle(cell* handle); void visit_object_array(cell* start, cell* end); - void visit_slots(object* ptr, cell payload_start); void visit_slots(object* ptr); void visit_stack_elements(segment* region, cell* top); void visit_data_roots(); @@ -172,22 +167,14 @@ void slot_visitor::visit_object_array(cell* start, cell* end) { visit_handle(start++); } -template -void slot_visitor::visit_slots(object* ptr, cell payload_start) { - cell* slot = (cell*)ptr; - cell* end = (cell*)((cell)ptr + payload_start); - - if (slot != end) { - slot++; - visit_object_array(slot, end); - } -} - template void slot_visitor::visit_slots(object* obj) { if (obj->type() == CALLSTACK_TYPE) visit_callstack_object((callstack*)obj); - else - visit_slots(obj, obj->binary_payload_start(fixup)); + else { + cell* start = (cell*)obj + 1; + cell* end = start + obj->slot_count(fixup); + visit_object_array(start, end); + } } template