AutoCollector.cpp   [plain text]


/*
 * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */

#include "AutoCollector.h"
#include "AutoDefs.h"
#include "AutoEnvironment.h"
#include "AutoList.h"
#include "AutoListTypes.h"
#include "AutoRange.h"
#include "AutoWriteBarrier.h"
#include "AutoZone.h"


namespace Auto {

    //----- Collector -----//
    
        
    //
    // check_roots
    //
    // Scan root blocks.
    //
    void Collector::check_roots() {
        if (_is_partial) {
            scan_retained_and_old_blocks();
        } else {
            scan_retained_blocks();
        }
       
        scan_root_ranges();
    }


    //
    // collect
    //
    // Collect scans memory for reachable objects.  Unmarked blocks are available to
    // be garbaged.  Returns "uninterrupted"
    //
    void Collector::collect(bool use_pending) {
        // scan memory
        if (use_pending)
            _zone->set_use_pending();
        else
            _zone->clear_use_pending();
        scan();
    }


    //
    // scan_barrier
    //
    // Used by collectors to synchronize with concurrent mutators.
    //
    void Collector::scan_barrier() {
        scan_end = auto_date_now();
        // write barriers should no longer repend blocks
        // NOTE:  this assumes NO THREADS ARE SUSPENDED at this point.
        // NOTE: we exit scanning with the enlivening lock held, so that Zone::collect() can
        // hold onto it until weak references and generational side data is cleared.
        spin_lock(_zone->enlivening_lock());
        PointerList& enlivening_queue = _zone->enlivening_queue();
        // pointers in the enlivening queue need to be transitively scanned.
        void **buffer = (void**)enlivening_queue.buffer();
        for (usword_t i = 0, count = enlivening_queue.count(); i < count; ++i) {
            _zone->repend(buffer[i]);
        }
        enlivening_queue.clear_count();
        enlivening_queue.uncommit();
    }
};