1/*
2 * Copyright (c) 2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20/*
21    WriteBarrier.h
22    Write Barrier for Generational GC
23    Copyright (c) 2004-2011 Apple Inc. All rights reserved.
24 */
25
26#pragma once
27#ifndef __AUTO_WRITE_BARRIER__
28#define __AUTO_WRITE_BARRIER__
29
30#include "Configuration.h"
31#include "Definitions.h"
32#include "Range.h"
33
34
35namespace Auto {
36
37
38    //
39    // Forward declarations
40    //
41    class Zone;
42
43
44    //----- WriteBarrier -----//
45
46    class WriteBarrier : public Range {
47
48      private:
49
50        void           *_base;                              // base address of managed range
51        usword_t       _protect;                            // protected space to base of write barrier
52
53      public:
54
55        //
56        // card values
57        //
58        enum {
59            card_unmarked = 0,
60            card_marked_untouched = 0x1,
61            card_marked = 0x3
62        };
63
64
65        //
66        // Constructor
67        //
68        // Set up cached allocation of use.
69        //
70        WriteBarrier(void *base, void *address, const usword_t size, const usword_t protect = 0)
71            : Range(address, size), _base(base), _protect(protect)
72        {
73        }
74
75
76        //
77        // bytes_needed
78        //
79        // Returns the number of write barrier bytes needed to represent 'n' actual bytes.
80        //
81        static inline const usword_t bytes_needed(usword_t n) {
82            return partition2(n, write_barrier_quantum_log2);
83        }
84
85
86        //
87        // card_index
88        //
89        // Return the write barrier card index for the specified address.
90        //
91        inline const usword_t card_index(void *address) const {
92            uintptr_t normalized = (uintptr_t)address - (uintptr_t)_base;
93            usword_t i = normalized >> write_barrier_quantum_log2;
94            ASSERTION(_protect <= i);
95            ASSERTION(i < size());
96            return i;
97        }
98
99        //
100        // contains_card
101        //
102        // Returns true if the specified address is managed by this write-barrier.
103        //
104        inline bool contains_card(void *address) {
105            usword_t i = card_index(address);
106            return (_protect <= i && i < size());
107        }
108
109
110        //
111        // card_address
112        //
113        // Return the base address of the range managed by the specified card index.
114        //
115        inline void *card_address(usword_t i) const { return displace(_base, i << write_barrier_quantum_log2); }
116
117
118        //
119        // is_card_marked
120        //
121        // Test to see if card i is marked.
122        //
123        inline bool is_card_marked(usword_t i) { return ((unsigned char *)address())[i] != card_unmarked; }
124
125
126        //
127        // mark_card
128        //
129        // Marks the card at index i.
130        //
131        inline void mark_card(usword_t i) {
132            ((unsigned char *)address())[i] = card_marked;
133        }
134
135        //
136        // mark_cards_untouched
137        //
138        // Used by the write-barrier repair algorithm. Transitions all cards that are currently marked from card_marked -> card_marked_untouched.
139        //
140        usword_t mark_cards_untouched();
141
142        //
143        // clear_untouched_cards
144        //
145        // Used by the write-barrier repair algorithm. Uses compare and swap to effect the transition card_marked_untouched -> card_unmarked.
146        //
147        usword_t clear_untouched_cards();
148
149
150        //
151        // is_card_marked
152        //
153        // Checks to see if the card corresponding to .
154        //
155        inline bool is_card_marked(void *address) {
156            usword_t i = card_index(address);
157            return is_card_marked(i);
158        }
159
160
161        //
162        // mark_card
163        //
164        // Mark the write barrier card for the specified address.
165        //
166        inline void mark_card(void *address) {
167            const usword_t i = card_index(address);
168            mark_card(i);
169        }
170
171
172        //
173        // mark_cards
174        //
175        // Mark the write barrier cards corresponding to the specified address range.
176        //
177        inline void mark_cards(void *address, const usword_t size) {
178            usword_t i = card_index(address);
179            const usword_t j = card_index(displace(address, size - 1));
180            for ( ; i <= j; i++) mark_card(i);
181        }
182
183
184        //
185        // scan_marked_ranges
186        //
187        // Scan ranges in block that are marked in the write barrier.
188        //
189#ifdef __BLOCKS__
190        typedef void (^write_barrier_scanner_t) (const Range&, WriteBarrier*);
191#else
192        class write_barrier_scanner {
193        public:
194            virtual void operator() (const Range &range, WriteBarrier *wb) = 0;
195        };
196        typedef write_barrier_scanner &write_barrier_scanner_t;
197#endif
198
199        void scan_marked_ranges(void *address, const usword_t size, write_barrier_scanner_t scanner);
200        void scan_marked_ranges(void *address, const usword_t size, void (*scanner) (const Range&, WriteBarrier*, void*), void *arg);
201
202
203        //
204        // range_has_marked_cards
205        //
206        // Returns true if range intersects a range that has cards marked.
207        //
208        bool range_has_marked_cards(void *address, const usword_t size);
209    };
210
211
212};
213
214
215#endif // __AUTO_WRITE_BARRIER__
216
217