1
2
3
4 package joeq.Allocator;
5
6 import joeq.Class.PrimordialClassLoader;
7 import joeq.Class.jq_Class;
8 import joeq.Class.jq_StaticField;
9 import joeq.Class.jq_Type;
10 import joeq.Memory.Address;
11 import joeq.Memory.CodeAddress;
12 import joeq.Memory.HeapAddress;
13 import joeq.Memory.StackAddress;
14 import joeq.Runtime.Debug;
15 import joeq.Runtime.Unsafe;
16 import joeq.Scheduler.jq_NativeThread;
17 import joeq.Scheduler.jq_RegisterState;
18 import joeq.Scheduler.jq_Thread;
19 import joeq.Scheduler.jq_ThreadQueue;
20
21 /***
22 * SemiConservative
23 *
24 * @author John Whaley
25 * @version $Id: SemiConservative.java 1869 2004-08-09 08:22:27Z joewhaley $
26 */
27 public abstract class SemiConservative {
28
29 public static void collect() {
30 if (true) Debug.writeln("Starting collection.");
31
32 jq_Thread t = Unsafe.getThreadBlock();
33 t.disableThreadSwitch();
34
35 jq_NativeThread.suspendAllThreads();
36
37 if (true) Debug.writeln("Threads suspended.");
38 SimpleAllocator s = (SimpleAllocator) DefaultHeapAllocator.def();
39 if (true) Debug.writeln("--> Marking roots.");
40 scanRoots();
41 if (true) Debug.writeln("--> Marking queue.");
42 s.scanGCQueue();
43 if (true) Debug.writeln("--> Sweeping.");
44 s.sweep();
45
46 if (true) Debug.writeln("Resuming threads.");
47 jq_NativeThread.resumeAllThreads();
48
49 t.enableThreadSwitch();
50 }
51
52 public static void scanRoots() {
53 scanStatics();
54 scanAllThreads();
55 }
56
57 /***
58 * Scan static variables for object references.
59 */
60 public static void scanStatics() {
61
62 jq_Type[] types = PrimordialClassLoader.loader.getAllTypes();
63 int num = PrimordialClassLoader.loader.getNumTypes();
64 for (int i = 0; i < num; ++i) {
65 Object o = types[i];
66 if (o instanceof jq_Class) {
67 jq_Class c = (jq_Class) o;
68 if (c.isSFInitialized()) {
69 jq_StaticField[] sfs = c.getDeclaredStaticFields();
70 for (int j=0; j<sfs.length; ++j) {
71 jq_StaticField sf = sfs[j];
72 jq_Type t = sf.getType();
73 if (t.isReferenceType() && !t.isAddressType()) {
74 if (SimpleAllocator.TRACE_GC) {
75 Debug.write(sf.getDeclaringClass().getDesc());
76 Debug.write(" ");
77 Debug.writeln(sf.getName());
78 }
79 HeapAddress a = sf.getAddress();
80 DefaultHeapAllocator.processObjectReference(a);
81 }
82 }
83 }
84 }
85 }
86 }
87
88 public static void scanAllThreads() {
89 if (jq_NativeThread.allNativeThreadsInitialized()) {
90 for (int i = 0; i < jq_NativeThread.native_threads.length; ++i) {
91 jq_NativeThread nt = jq_NativeThread.native_threads[i];
92 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning native thread ", i);
93 scanQueuedThreads(nt);
94
95 }
96 } else {
97 jq_NativeThread nt = Unsafe.getThreadBlock().getNativeThread();
98 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning initial native thread");
99 scanQueuedThreads(nt);
100 }
101 scanCurrentThreadStack(3);
102 }
103
104 public static void scanQueuedThreads(jq_NativeThread nt) {
105 for (int i = 0; i < jq_NativeThread.NUM_OF_QUEUES; ++i) {
106 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning thread queue ", i);
107 scanThreadQueue(nt.getReadyQueue(i));
108 }
109 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning idle queue");
110 scanThreadQueue(nt.getIdleQueue());
111 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning transfer queue");
112 scanThreadQueue(nt.getTransferQueue());
113 }
114
115 public static void scanThreadQueue(jq_ThreadQueue q) {
116 jq_Thread t = q.peek();
117 while (t != null) {
118 scanThreadStack(t);
119
120 t = t.getNext();
121 }
122 }
123
124 public static void scanCurrentThreadStack(int skip) {
125 if (SimpleAllocator.TRACE_GC) Debug.writeln("Scanning current thread stack");
126 StackAddress fp = StackAddress.getBasePointer();
127 StackAddress sp = StackAddress.getStackPointer();
128 CodeAddress ip = (CodeAddress) fp.offset(HeapAddress.size()).peek();
129 while (!fp.isNull()) {
130 if (SimpleAllocator.TRACE_GC) {
131 Debug.write("Scanning stack frame fp=", fp);
132 Debug.write(" sp=", sp);
133 Debug.writeln(" ip=", ip);
134 }
135 if (--skip < 0) {
136 while (fp.difference(sp) > 0) {
137 if (SimpleAllocator.TRACE_GC) {
138 Debug.write("sp: ", sp);
139 Debug.writeln(" ", sp.peek());
140 }
141 addConservativeAddress(sp);
142 sp = (StackAddress) sp.offset(HeapAddress.size());
143 }
144 } else {
145 if (SimpleAllocator.TRACE_GC) Debug.writeln("Skipping this frame.");
146 }
147 ip = (CodeAddress) fp.offset(HeapAddress.size()).peek();
148 sp = fp;
149 fp = (StackAddress) fp.peek();
150 }
151 }
152
153 public static void scanThreadStack(jq_Thread t) {
154 jq_RegisterState s = t.getRegisterState();
155 StackAddress fp = s.getEbp();
156 CodeAddress ip = s.getEip();
157 StackAddress sp = s.getEsp();
158 while (!fp.isNull()) {
159 while (fp.difference(sp) > 0) {
160 addConservativeAddress(sp);
161 sp = (StackAddress) sp.offset(HeapAddress.size());
162 }
163 ip = (CodeAddress) fp.offset(HeapAddress.size()).peek();
164 sp = fp;
165 fp = (StackAddress) fp.peek();
166 }
167 }
168
169 public static void addConservativeAddress(Address a) {
170 DefaultHeapAllocator.processPossibleObjectReference(a);
171 }
172
173 }