WriteBarrier.h   [plain text]


/*
 * Copyright (c) 2011 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@
 */
/*
    WriteBarrier.h
    Write Barrier for Generational GC
    Copyright (c) 2004-2011 Apple Inc. All rights reserved.
 */

#pragma once
#ifndef __AUTO_WRITE_BARRIER__
#define __AUTO_WRITE_BARRIER__

#include "Configuration.h"
#include "Definitions.h"
#include "Range.h"


namespace Auto {

    
    //
    // Forward declarations
    //
    class Zone;
    

    //----- WriteBarrier -----//

    class WriteBarrier : public Range {
    
      private:
      
        void           *_base;                              // base address of managed range
        usword_t       _protect;                            // protected space to base of write barrier
        
      public:

        //
        // card values
        //
        enum {
            card_unmarked = 0,
            card_marked_untouched = 0x1,
            card_marked = 0x3
        };
      
      
        //
        // Constructor
        //
        // Set up cached allocation of use.
        //
        WriteBarrier(void *base, void *address, const usword_t size, const usword_t protect = 0)
            : Range(address, size), _base(base), _protect(protect)
        {
        }

        
        //
        // bytes_needed
        //
        // Returns the number of write barrier bytes needed to represent 'n' actual bytes.
        //
        static inline const usword_t bytes_needed(usword_t n) {
            return partition2(n, write_barrier_quantum_log2);
        }
        
        
        //
        // card_index
        //
        // Return the write barrier card index for the specified address.
        //
        inline const usword_t card_index(void *address) const {
            uintptr_t normalized = (uintptr_t)address - (uintptr_t)_base;
            usword_t i = normalized >> write_barrier_quantum_log2;
            ASSERTION(_protect <= i);
            ASSERTION(i < size());
            return i;
        }
        
        //
        // contains_card
        //
        // Returns true if the specified address is managed by this write-barrier.
        //
        inline bool contains_card(void *address) {
            usword_t i = card_index(address);
            return (_protect <= i && i < size());
        }
        
        
        //
        // card_address
        //
        // Return the base address of the range managed by the specified card index.
        //
        inline void *card_address(usword_t i) const { return displace(_base, i << write_barrier_quantum_log2); }
        
        
        //
        // is_card_marked
        //
        // Test to see if card i is marked.
        //
        inline bool is_card_marked(usword_t i) { return ((unsigned char *)address())[i] != card_unmarked; }
        
        
        //
        // mark_card
        //
        // Marks the card at index i.
        //
        inline void mark_card(usword_t i) {
            ((unsigned char *)address())[i] = card_marked;
        }

        //
        // mark_cards_untouched
        //
        // Used by the write-barrier repair algorithm. Transitions all cards that are currently marked from card_marked -> card_marked_untouched.
        //
        usword_t mark_cards_untouched();
        
        //
        // clear_untouched_cards
        //
        // Used by the write-barrier repair algorithm. Uses compare and swap to effect the transition card_marked_untouched -> card_unmarked.
        //
        usword_t clear_untouched_cards();
        
        
        //
        // is_card_marked
        //
        // Checks to see if the card corresponding to .
        //
        inline bool is_card_marked(void *address) {
            usword_t i = card_index(address);
            return is_card_marked(i);
        }
        
        
        //
        // mark_card
        //
        // Mark the write barrier card for the specified address.
        //
        inline void mark_card(void *address) {
            const usword_t i = card_index(address);
            mark_card(i);
        }
        
        
        //
        // mark_cards
        //
        // Mark the write barrier cards corresponding to the specified address range.
        //
        inline void mark_cards(void *address, const usword_t size) {
            usword_t i = card_index(address);
            const usword_t j = card_index(displace(address, size - 1));
            for ( ; i <= j; i++) mark_card(i);
        }

        
        //
        // scan_marked_ranges
        //
        // Scan ranges in block that are marked in the write barrier.
        //
#ifdef __BLOCKS__
        typedef void (^write_barrier_scanner_t) (const Range&, WriteBarrier*);
#else
        class write_barrier_scanner {
        public:
            virtual void operator() (const Range &range, WriteBarrier *wb) = 0;
        };
        typedef write_barrier_scanner &write_barrier_scanner_t;
#endif

        void scan_marked_ranges(void *address, const usword_t size, write_barrier_scanner_t scanner);
        void scan_marked_ranges(void *address, const usword_t size, void (*scanner) (const Range&, WriteBarrier*, void*), void *arg);
        
        
        //
        // range_has_marked_cards
        //
        // Returns true if range intersects a range that has cards marked.
        //
        bool range_has_marked_cards(void *address, const usword_t size);
    };

    
};


#endif // __AUTO_WRITE_BARRIER__