1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
21
package org.jnode.vm.memmgr.generational;
22
23
import org.jnode.annotation.Inline;
24
import org.jnode.annotation.MagicPermission;
25
import org.jnode.vm.ObjectVisitor;
26
import org.jnode.vm.classmgr.ObjectLayout;
27
import org.jnode.vm.memmgr.HeapHelper;
28
import org.jnode.vm.scheduler.SpinLock;
29
import org.vmmagic.pragma.Uninterruptible;
30
import org.vmmagic.pragma.UninterruptiblePragma;
31
import org.vmmagic.unboxed.Address;
32
import org.vmmagic.unboxed.ObjectReference;
33
import org.vmmagic.unboxed.Offset;
34
import org.vmmagic.unboxed.Word;
35
36
/**
37
 * An abstract heap class.
38
 * <p/>
39
 * All changes to the structure of the heap must be made exclusive by
40
 * {@link #lock()} and {@link #unlock()}.
41
 * 
42
 * @author epr
43
 */
44
@MagicPermission
45
abstract class VmAbstractHeap extends SpinLock implements Uninterruptible {
46
47
    /**
48
     * Start address of this heap (inclusive)
49
     */
50
    protected Address start;
51
    /**
52
     * End address of this heap (exclusive)
53
     */
54
    protected Address end;
55
    /**
56
     * Size of this heap in bytes
57
     */
58
    private int size;
59
    /**
60
     * Size of an object header in bytes
61
     */
62
    protected int headerSize;
63
    /**
64
     * Offset of the age field in an object header
65
     */
66
    protected Offset ageOffset;
67
    /**
68
     * Offset of the number of reference field in an object header
69
     */
70
    protected Offset nbRefOffset;
71
    /**
72
     * Offset of the flags field in an object header
73
     */
74
    protected Offset flagsOffset;
75
    /**
76
     * Offset of the type information block field in an object header
77
     */
78
    protected Offset tibOffset;
79
    /**
80
     * Start address of allocation bitmap
81
     */
82
    protected Address allocationBitmapPtr;
83
84
    /**
85
     * Default marker for free object space (marker in VMT field)
86
     */
87
    protected Object FREE = null;
88
    protected HeapHelper helper;
89
90
    public VmAbstractHeap(HeapHelper helper) {
91
        this.helper = helper;
92
    }
93
94
    /**
95
     * Initialization method for the private fields in this class. This method
96
     * must be called, after start and end have been set.
97
     * 
98
     * @param slotSize
99
     */
100
    protected final void initializeAbstract(int slotSize) {
101
        this.headerSize = (ObjectLayout.HEADER_SLOTS + 3) * slotSize;
102
        this.flagsOffset = Offset.fromIntSignExtend(ObjectLayout.FLAGS_SLOT * slotSize);
103
        this.tibOffset = Offset.fromIntSignExtend(ObjectLayout.TIB_SLOT * slotSize);
104
        this.ageOffset = Offset.fromIntSignExtend(ObjectLayout.COLLECTION_AGE_SLOT * slotSize);
105
        this.nbRefOffset = Offset.fromIntSignExtend(ObjectLayout.NB_REFS_SLOT * slotSize);
106
        this.size = end.toWord().sub(start.toWord()).toInt();
107
    }
108
109
    /**
110
     * Gets the size in bytes of this heap.
111
     * 
112
     * @return int
113
     */
114
    @Inline
115
    public final int getSize() {
116
        return size;
117
    }
118
119
    /**
120
     * Is the given address the address of an allocated object on this heap?
121
     * 
122
     * @param addr
123
     * @return boolean
124
     */
125
    @Inline
126
    public final boolean isObject(Address addr) {
127
        if (addr.LT(start) || addr.GE(end)) {
128
            // The object if not within this heap
129
            return false;
130
        }
131
132
        final int offset = addr.toWord().sub(start.toWord()).toInt();
133
        int bit = offset / ObjectLayout.OBJECT_ALIGN;
134
        final Offset idx = Offset.fromIntZeroExtend(bit / 8);
135
        final int mask = 1 << (bit & 7);
136
        final Address bitmapPtr = this.allocationBitmapPtr;
137
        final int value = bitmapPtr.loadByte(idx);
138
        return ((value & mask) == mask);
139
    }
140
141
    /**
142
     * Is the given address an address within this heap. If so, this does not
143
     * always mean that the address is a valid object!
144
     * 
145
     * @param addr
146
     * @return boolean
147
     */
148
    @Inline
149
    protected final boolean inHeap(Address addr) {
150
        return (addr.GE(start) && addr.LT(end));
151
    }
152
153
    /**
154
     * Change a bit in the allocation bitmap.
155
     * 
156
     * @param object
157
     * @param on
158
     */
159
    @Inline
160
    protected final void setAllocationBit(Object object, boolean on) {
161
        final Address addr = ObjectReference.fromObject(object).toAddress();
162
        if (addr.LT(start) || addr.GE(end)) {
163
            return;
164
        }
165
166
        final int offset = addr.toWord().sub(start.toWord()).toInt();
167
        final int bit = offset / ObjectLayout.OBJECT_ALIGN;
168
        final Offset idx = Offset.fromIntZeroExtend(bit / 8);
169
        final int mask = 1 << (bit & 7);
170
        final Address bitmapPtr = this.allocationBitmapPtr;
171
        int value = bitmapPtr.loadByte(idx);
172
        if (on) {
173
            value |= mask;
174
        } else {
175
            value &= ~mask;
176
        }
177
        bitmapPtr.store((byte) value, idx);
178
    }
179
180
    /**
181
     * Initialize this heap
182
     * 
183
     * @param start
184
     *            Start address of this heap
185
     * @param end
186
     *            End address of this heap (first address after this heap)
187
     * @param slotSize
188
     */
189
    protected abstract void initialize(Address start, Address end, int slotSize);
190
191
    /**
192
     * Let a selected set of objects in this heap accept the given
193
     * <code>visitor</code>. The selection is made based on the objectflags. The
194
     * objectflags are masked by flagsMask and the result is compared with
195
     * flagsValue, if they are equal the object is visited.
196
     * 
197
     * @param visitor
198
     * @param locking
199
     *            If true, use lock/unlock while proceeding to the next object.
200
     * @param flagsMask
201
     * @param flagsValue
202
     * @throws UninterruptiblePragma
203
     */
204
    protected abstract void walk(ObjectVisitor visitor, boolean locking, Word flagsMask,
205
            Word flagsValue) throws UninterruptiblePragma;
206
}