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    Range.h
22    Contiguous Address Range
23    Copyright (c) 2004-2011 Apple Inc. All rights reserved.
24 */
25
26#pragma once
27#ifndef __AUTO_RANGE__
28#define __AUTO_RANGE__
29
30
31#include "Definitions.h"
32
33
34namespace Auto {
35
36    //----- Range -----//
37
38    //
39    // Manage an area of memory
40    //
41
42    class Range {
43
44      private:
45
46        void *_address;                                     // start of range
47        void *_end;                                         // end of the range (one byte beyond last usable space)
48
49      public:
50
51        //
52        // Constructors
53        //
54        Range()                             : _address(NULL),    _end(NULL) {}
55        Range(void *address)                : _address(address), _end(address) {}
56        Range(void *address, void *end)     : _address(address), _end(end) {}
57        Range(void *address, usword_t size) : _address(address), _end(displace(address, size)) {}
58
59
60        //
61        // Accessors
62        //
63        inline       Range&   range()                                       { return *this; }
64        inline       void     *address()                              const { return _address; }
65        inline       void     *end()                                  const { return _end; }
66        inline const usword_t size()                                  const { return (uintptr_t)_end - (uintptr_t)_address; }
67        inline       void     set_address(void *address)                    { _address = address; }
68        inline       void     set_end(void *end)                            { _end = end; }
69        inline       void     set_size(usword_t size)                       { _end = displace(_address, size); }
70        inline       void     set_range(void *address, void *end)           { _address = address; _end = end; }
71        inline       void     set_range(void *address, usword_t size)       { _address = address; _end = displace(address, size); }
72        inline       void     set_range(Range range)                        { _address = range.address(); _end = range.end(); }
73        inline       void     adjust_address(intptr_t delta)                { _address = displace(_address, delta); }
74        inline       void     adjust_end(intptr_t delta)                    { _end = displace(_end, delta); }
75        inline       void     adjust(intptr_t delta)                        { _address = displace(_address, delta), _end = displace(_end, delta); }
76
77
78        //
79        // is_empty
80        //
81        // Returns true if the range is empty.
82        //
83        inline bool is_empty() { return _address == _end; }
84
85
86        //
87        // in_range
88        //
89        // Returns true if the specified address is in range.
90        // This form reduces the number of branches.  Works well with invariant lo and hi.
91        //
92        static inline const bool in_range(void *lo, void *hi, void *address) {
93            uintptr_t lo_as_int = (uintptr_t)lo;
94            uintptr_t hi_as_int = (uintptr_t)hi;
95            uintptr_t diff = hi_as_int - lo_as_int;
96            uintptr_t address_as_int = (uintptr_t)address;
97            return (address_as_int - lo_as_int) < diff;
98        }
99        inline const bool in_range(void *address) const { return in_range(_address, _end, address); }
100
101
102        //
103        // operator ==
104        //
105        // Used to locate entry in list or hash table (use is_range for exaxt match.)
106        inline const bool operator==(const Range *range)  const { return _address == range->_address; }
107        inline const bool operator==(const Range &range)  const { return _address == range._address; }
108
109        //
110        // is_range
111        //
112        // Return true if the ranges are equivalent.
113        //
114        inline const bool is_range(const Range& range) const { return _address == range._address && _end == range._end; }
115
116
117        //
118        // clear
119        //
120        // Initialize the range to zero.
121        //
122        inline void clear() { bzero(address(), size()); }
123
124        //
125        // uncommit
126        //
127        // Tell the operating system the contents of the pages can be purged.
128        //
129        inline void uncommit() { uncommit_memory(address(), size()); }
130
131        //
132        // commit
133        //
134        // Tell the operating system the pages in this range are about to be reused.
135        //
136        inline void commit() { commit_memory(address(), size()); }
137
138        //
139        // expand_range
140        //
141        // Expand the bounds with the specified range.
142        //
143        inline void expand_range(void *address) {
144            if (_address > address) _address = address;
145            if (_end < address) _end = address;
146        }
147        inline void expand_range(Range& range) {
148            expand_range(range.address());
149            expand_range(range.end());
150        }
151
152
153        //
154        // relative_address
155        //
156        // Converts an absolute address to an address relative to this address.
157        //
158        inline void *relative_address(void *address) const { return (void *)((uintptr_t)address - (uintptr_t)_address); }
159
160
161        //
162        // absolute_address
163        //
164        // Converts an address relative to this address to an absolute address.
165        //
166        inline void *absolute_address(void *address) const { return (void *)((uintptr_t)address + (uintptr_t)_address); }
167
168
169    };
170
171};
172
173#endif // __AUTO_RANGE__
174
175