/* Understands how to read the inside of an object and find all references * located within. It copies the objects pointed to, but does not follow into * those further (ie, not recursive) */ void GarbageCollector::scan_object(Object* obj) { Object* slot; // If this object's refs are weak, then add it to the weak_refs // vector and don't look at it otherwise. if(obj->RefsAreWeak) { if(!weak_refs) { weak_refs = new ObjectArray(0); } weak_refs->push_back(obj); return; } if(obj->klass() && obj->klass()->reference_p()) { slot = saw_object(obj->klass()); if(slot) object_memory->set_class(obj, slot); } if(obj->ivars() && obj->ivars()->reference_p()) { slot = saw_object(obj->ivars()); if(slot) obj->ivars(object_memory->state, slot); } TypeInfo* ti = object_memory->type_info[obj->obj_type]; assert(ti); ObjectMark mark(this); ti->mark(obj, mark); }
/** * Scans the specified Object +obj+ for references to other Objects, and * marks those Objects as reachable. Understands how to read the inside of * an Object and find all references located within. For each reference * found, it marks the object pointed to as live (which may trigger * movement of the object in a copying garbage collector), but does not * recursively scan into the referenced object (since such recursion could * be arbitrarily deep, depending on the object graph, and this could cause * the stack to blow up). * /param obj The Object to be scanned for references to other Objects. */ void GarbageCollector::scan_object(Object* obj) { Object* slot; #ifdef ENABLE_OBJECT_WATCH if(watched_p(obj)) { std::cout << "detected " << obj << " during scan_object.\n"; } #endif // Check and update an inflated header if(obj->inflated_header_p()) { obj->inflated_header()->reset_object(obj); } slot = saw_object(obj->klass()); if(slot) obj->klass(object_memory_, force_as<Class>(slot)); if(obj->ivars()->reference_p()) { slot = saw_object(obj->ivars()); if(slot) obj->ivars(object_memory_, slot); } // Handle Tuple directly, because it's so common if(Tuple* tup = try_as<Tuple>(obj)) { int size = tup->num_fields(); for(int i = 0; i < size; i++) { slot = tup->field[i]; if(slot->reference_p()) { slot = saw_object(slot); if(slot) { tup->field[i] = slot; object_memory_->write_barrier(tup, slot); } } } } else { TypeInfo* ti = object_memory_->type_info[obj->type_id()]; ObjectMark mark(this); ti->mark(obj, mark); } }
/** * Scans the specified Object +obj+ for references to other Objects, and * marks those Objects as reachable. Understands how to read the inside of * an Object and find all references located within. For each reference * found, it marks the object pointed to as live (which may trigger * movement of the object in a copying garbage collector), but does not * recursively scan into the referenced object (since such recursion could * be arbitrarily deep, depending on the object graph, and this could cause * the stack to blow up). * /param obj The Object to be scanned for references to other Objects. */ void GarbageCollector::scan_object(Object* obj) { #ifdef ENABLE_OBJECT_WATCH if(watched_p(obj)) { std::cout << "detected " << obj << " during scan_object.\n"; } #endif // We set scanned here before we finish scanning the object. // This is done so we don't have a race condition while we're // scanning the object and another thread updates a field during // the phase where the object is partially scanned. scanned_object(obj); if(Object* klass = saw_object(obj->klass())) { obj->klass(object_memory_, force_as<Class>(klass)); } if(obj->ivars()->reference_p()) { if(Object* ivars = saw_object(obj->ivars())) { obj->ivars(object_memory_, ivars); } } // Handle Tuple directly, because it's so common if(Tuple* tup = try_as<Tuple>(obj)) { native_int size = tup->num_fields(); for(native_int i = 0; i < size; i++) { Object* slot = tup->field[i]; if(slot->reference_p()) { if(Object* moved = saw_object(slot)) { tup->field[i] = moved; object_memory_->write_barrier(tup, moved); } } } } else { TypeInfo* ti = object_memory_->type_info[obj->type_id()]; ObjectMark mark(this); ti->mark(obj, mark); } }