Source code: GC/GCBits.java
1 // GCBits.java, created Wed Sep 25 20:04:21 2002 by laudney
2 // Copyright (C) 2001-3 laudney <laudney@acm.org>
3 // Licensed under the terms of the GNU LGPL; see COPYING for details.
4 package GC;
5
6 import java.util.HashSet;
7
8 import Allocator.MemUnit;
9 import Allocator.SimpleAllocator;
10 import Bootstrap.PrimordialClassLoader;
11 import Clazz.jq_Class;
12 import Memory.HeapAddress;
13 import Util.BitString;
14
15 /**
16 * GCBits
17 *
18 * PRE-REQUISITE: All the objects and arrays are allocated align8
19 *
20 * @author laudney <laudney@acm.org>
21 * @version $Id: GCBits.java,v 1.11 2003/05/12 10:05:17 joewhaley Exp $
22 */
23 public class GCBits {
24
25 protected static final int bitLength = SimpleAllocator.BLOCK_SIZE / 8;
26 protected static final int byteLength = SimpleAllocator.BLOCK_SIZE / 64;
27
28 protected HeapAddress blockHead, blockEnd;
29
30 /**
31 * Each bit in allocbits corresponds to 8 bytes on the heap. When an object is
32 * allocated and aligned on 8 byte boundary, the bit in allocbits corresponding
33 * to the starting 8 bytes (including HEADER) of the object is set.
34 */
35 private final BitString allocbits = new BitString(bitLength);
36
37 /**
38 * Each bit in markbits corresponds to 8 bytes on the heap. When an object
39 * is reachable from TraceRootSet, the bit in markbits corresponding to the
40 * starting 8 bytes (including HEADER) of the object is set.
41 */
42 private final BitString markbits = new BitString(bitLength);
43
44 // Never created normally. Always created with allocateObject_nogc.
45 public GCBits(HeapAddress blockHead, HeapAddress blockEnd) {
46 this.blockHead = blockHead;
47 this.blockEnd = blockEnd;
48 GCBitsManager.register(this);
49 }
50
51 public void set(HeapAddress addr) {
52 allocbits.set((addr.difference(blockHead)) / 8);
53 }
54
55 public void unset(HeapAddress addr) {
56 allocbits.clear((addr.difference(blockHead)) / 8);
57 }
58
59 public boolean isSet(HeapAddress addr) {
60 return allocbits.get((addr.difference(blockHead)) / 8);
61 }
62
63 public void mark(HeapAddress addr) {
64 markbits.set((addr.difference(blockHead)) / 8);
65 }
66
67 public void unmark(HeapAddress addr) {
68 markbits.clear((addr.difference(blockHead)) / 8);
69 }
70
71 public boolean isMarked(HeapAddress addr) {
72 return markbits.get((addr.difference(blockHead)) / 8);
73 }
74
75 public HashSet diff() {
76 BitString sweepbits = (BitString) markbits.clone();
77 sweepbits.xor(allocbits);
78 BitString.ForwardBitStringIterator iter = sweepbits.iterator();
79 HashSet units = new HashSet();
80 int i, j;
81 while (iter.hasNext()) {
82 i = iter.nextIndex(); // head of a sweepable object
83 j = allocbits.firstSet(i); // end of a sweepable object
84 if (j != -1) {
85 units.add(new MemUnit((HeapAddress)blockHead.offset(i * 8), (j - i) * 8));
86 } else {
87 units.add(new MemUnit((HeapAddress)blockHead.offset(i * 8), blockEnd));
88 }
89 }
90 return units;
91 }
92
93 public static final jq_Class _class = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("LGC/GCBits;");
94 }