annotate src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp @ 453:c96030fff130

6684579: SoftReference processing can be made more efficient Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not. Reviewed-by: jmasa
author ysr
date Thu, 20 Nov 2008 16:56:09 -0800
parents 81cd571500b0
children ad8c8ca4ab0f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25
a61af66fc99e Initial load
duke
parents:
diff changeset
26 // Tasks for parallel compaction of the old generation
a61af66fc99e Initial load
duke
parents:
diff changeset
27 //
a61af66fc99e Initial load
duke
parents:
diff changeset
28 // Tasks are created and enqueued on a task queue. The
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // tasks for parallel old collector for marking objects
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // are MarkFromRootsTask and ThreadRootsMarkingTask.
a61af66fc99e Initial load
duke
parents:
diff changeset
31 //
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // MarkFromRootsTask's are created
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // with a root group (e.g., jni_handles) and when the do_it()
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // method of a MarkFromRootsTask is executed, it starts marking
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // form it's root group.
a61af66fc99e Initial load
duke
parents:
diff changeset
36 //
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // ThreadRootsMarkingTask's are created for each Java thread. When
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // the do_it() method of a ThreadRootsMarkingTask is executed, it
a61af66fc99e Initial load
duke
parents:
diff changeset
39 // starts marking from the thread's roots.
a61af66fc99e Initial load
duke
parents:
diff changeset
40 //
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // The enqueuing of the MarkFromRootsTask and ThreadRootsMarkingTask
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // do little more than create the task and put it on a queue. The
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // queue is a GCTaskQueue and threads steal tasks from this GCTaskQueue.
a61af66fc99e Initial load
duke
parents:
diff changeset
44 //
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // In addition to the MarkFromRootsTask and ThreadRootsMarkingTask
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // tasks there are StealMarkingTask tasks. The StealMarkingTask's
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // steal a reference from the marking stack of another
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // thread and transitively marks the object of the reference
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // and internal references. After successfully stealing a reference
a61af66fc99e Initial load
duke
parents:
diff changeset
50 // and marking it, the StealMarkingTask drains its marking stack
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // stack before attempting another steal.
a61af66fc99e Initial load
duke
parents:
diff changeset
52 //
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // ThreadRootsMarkingTask
a61af66fc99e Initial load
duke
parents:
diff changeset
54 //
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // This task marks from the roots of a single thread. This task
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // enables marking of thread roots in parallel.
a61af66fc99e Initial load
duke
parents:
diff changeset
57 //
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 class ParallelTaskTerminator;
a61af66fc99e Initial load
duke
parents:
diff changeset
60
a61af66fc99e Initial load
duke
parents:
diff changeset
61 class ThreadRootsMarkingTask : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
62 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
63 JavaThread* _java_thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
64 VMThread* _vm_thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
65 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
66 ThreadRootsMarkingTask(JavaThread* root) : _java_thread(root), _vm_thread(NULL) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
67 ThreadRootsMarkingTask(VMThread* root) : _java_thread(NULL), _vm_thread(root) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 char* name() { return (char *)"thread-roots-marking-task"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
72 };
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74
a61af66fc99e Initial load
duke
parents:
diff changeset
75 //
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // MarkFromRootsTask
a61af66fc99e Initial load
duke
parents:
diff changeset
77 //
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // This task marks from all the roots to all live
a61af66fc99e Initial load
duke
parents:
diff changeset
79 // objects.
a61af66fc99e Initial load
duke
parents:
diff changeset
80 //
a61af66fc99e Initial load
duke
parents:
diff changeset
81 //
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 class MarkFromRootsTask : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
85 enum RootType {
a61af66fc99e Initial load
duke
parents:
diff changeset
86 universe = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
87 jni_handles = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
88 threads = 3,
a61af66fc99e Initial load
duke
parents:
diff changeset
89 object_synchronizer = 4,
a61af66fc99e Initial load
duke
parents:
diff changeset
90 flat_profiler = 5,
a61af66fc99e Initial load
duke
parents:
diff changeset
91 management = 6,
a61af66fc99e Initial load
duke
parents:
diff changeset
92 jvmti = 7,
a61af66fc99e Initial load
duke
parents:
diff changeset
93 system_dictionary = 8,
a61af66fc99e Initial load
duke
parents:
diff changeset
94 vm_symbols = 9,
a61af66fc99e Initial load
duke
parents:
diff changeset
95 reference_processing = 10
a61af66fc99e Initial load
duke
parents:
diff changeset
96 };
a61af66fc99e Initial load
duke
parents:
diff changeset
97 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
98 RootType _root_type;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
100 MarkFromRootsTask(RootType value) : _root_type(value) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
101
a61af66fc99e Initial load
duke
parents:
diff changeset
102 char* name() { return (char *)"mark-from-roots-task"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 };
a61af66fc99e Initial load
duke
parents:
diff changeset
106
a61af66fc99e Initial load
duke
parents:
diff changeset
107 //
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // RefProcTaskProxy
a61af66fc99e Initial load
duke
parents:
diff changeset
109 //
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // This task is used as a proxy to parallel reference processing tasks .
a61af66fc99e Initial load
duke
parents:
diff changeset
111 //
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 class RefProcTaskProxy : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 ProcessTask & _rp_task;
a61af66fc99e Initial load
duke
parents:
diff changeset
116 uint _work_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
118 RefProcTaskProxy(ProcessTask & rp_task, uint work_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
119 : _rp_task(rp_task),
a61af66fc99e Initial load
duke
parents:
diff changeset
120 _work_id(work_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
121 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
122
a61af66fc99e Initial load
duke
parents:
diff changeset
123 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
124 virtual char* name() { return (char *)"Process referents by policy in parallel"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
125
a61af66fc99e Initial load
duke
parents:
diff changeset
126 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
127 };
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129
a61af66fc99e Initial load
duke
parents:
diff changeset
130
a61af66fc99e Initial load
duke
parents:
diff changeset
131 //
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // RefEnqueueTaskProxy
a61af66fc99e Initial load
duke
parents:
diff changeset
133 //
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // This task is used as a proxy to parallel reference processing tasks .
a61af66fc99e Initial load
duke
parents:
diff changeset
135 //
a61af66fc99e Initial load
duke
parents:
diff changeset
136
a61af66fc99e Initial load
duke
parents:
diff changeset
137 class RefEnqueueTaskProxy: public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 EnqueueTask& _enq_task;
a61af66fc99e Initial load
duke
parents:
diff changeset
140 uint _work_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
143 RefEnqueueTaskProxy(EnqueueTask& enq_task, uint work_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
144 : _enq_task(enq_task),
a61af66fc99e Initial load
duke
parents:
diff changeset
145 _work_id(work_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
146 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 virtual char* name() { return (char *)"Enqueue reference objects in parallel"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
149 virtual void do_it(GCTaskManager* manager, uint which)
a61af66fc99e Initial load
duke
parents:
diff changeset
150 {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 _enq_task.work(_work_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 };
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155
a61af66fc99e Initial load
duke
parents:
diff changeset
156 //
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // RefProcTaskExecutor
a61af66fc99e Initial load
duke
parents:
diff changeset
158 //
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // Task executor is an interface for the reference processor to run
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // tasks using GCTaskManager.
a61af66fc99e Initial load
duke
parents:
diff changeset
161 //
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 virtual void execute(ProcessTask& task);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 virtual void execute(EnqueueTask& task);
a61af66fc99e Initial load
duke
parents:
diff changeset
166 };
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 //
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // StealMarkingTask
a61af66fc99e Initial load
duke
parents:
diff changeset
171 //
a61af66fc99e Initial load
duke
parents:
diff changeset
172 // This task is used to distribute work to idle threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
173 //
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 class StealMarkingTask : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
176 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
177 ParallelTaskTerminator* const _terminator;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
181 char* name() { return (char *)"steal-marking-task"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 StealMarkingTask(ParallelTaskTerminator* t);
a61af66fc99e Initial load
duke
parents:
diff changeset
184
a61af66fc99e Initial load
duke
parents:
diff changeset
185 ParallelTaskTerminator* terminator() { return _terminator; }
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
188 };
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190 //
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
191 // StealRegionCompactionTask
0
a61af66fc99e Initial load
duke
parents:
diff changeset
192 //
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // This task is used to distribute work to idle threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
194 //
a61af66fc99e Initial load
duke
parents:
diff changeset
195
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
196 class StealRegionCompactionTask : public GCTask {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
197 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
198 ParallelTaskTerminator* const _terminator;
a61af66fc99e Initial load
duke
parents:
diff changeset
199 public:
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
200 StealRegionCompactionTask(ParallelTaskTerminator* t);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
201
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
202 char* name() { return (char *)"steal-region-task"; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
203 ParallelTaskTerminator* terminator() { return _terminator; }
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
206 };
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 //
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // UpdateDensePrefixTask
a61af66fc99e Initial load
duke
parents:
diff changeset
210 //
a61af66fc99e Initial load
duke
parents:
diff changeset
211 // This task is used to update the dense prefix
a61af66fc99e Initial load
duke
parents:
diff changeset
212 // of a space.
a61af66fc99e Initial load
duke
parents:
diff changeset
213 //
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 class UpdateDensePrefixTask : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
217 PSParallelCompact::SpaceId _space_id;
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
218 size_t _region_index_start;
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
219 size_t _region_index_end;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
222 char* name() { return (char *)"update-dense_prefix-task"; }
a61af66fc99e Initial load
duke
parents:
diff changeset
223
a61af66fc99e Initial load
duke
parents:
diff changeset
224 UpdateDensePrefixTask(PSParallelCompact::SpaceId space_id,
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
225 size_t region_index_start,
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
226 size_t region_index_end);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 };
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 //
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // DrainStacksCompactionTask
a61af66fc99e Initial load
duke
parents:
diff changeset
233 //
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
234 // This task processes regions that have been added to the stacks of each
0
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // compaction manager.
a61af66fc99e Initial load
duke
parents:
diff changeset
236 //
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // Trying to use one draining thread does not work because there are no
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // guarantees about which task will be picked up by which thread. For example,
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
239 // if thread A gets all the preloaded regions, thread A may not get a draining
0
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // task (they may all be done by other threads).
a61af66fc99e Initial load
duke
parents:
diff changeset
241 //
a61af66fc99e Initial load
duke
parents:
diff changeset
242
a61af66fc99e Initial load
duke
parents:
diff changeset
243 class DrainStacksCompactionTask : public GCTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
244 public:
375
81cd571500b0 6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents: 0
diff changeset
245 char* name() { return (char *)"drain-region-task"; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
246 virtual void do_it(GCTaskManager* manager, uint which);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 };