00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 # include "incls/_precompiled.incl"
00026
00027 # include <string.h>
00028
00029 # include "incls/_rSet.cpp.incl"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 rSet::rSet() {
00052 low_boundary = Universe::new_gen.low_boundary;
00053 high_boundary = Universe::old_gen.high_boundary;
00054 clear();
00055 Set_Byte_Map_Base(byte_for(NULL));
00056 assert(byte_for(low_boundary) == byte_map, "Checking start of map");
00057 }
00058
00059 void* rSet::operator new(size_t size) {
00060 assert((int(Universe::new_gen.low_boundary) & (card_size - 1)) == 0,
00061 "new must start at card boundary");
00062 assert((int(Universe::old_gen.low_boundary) & (card_size - 1)) == 0,
00063 "old must start at card boundary");
00064 assert((int(Universe::old_gen.high_boundary) & (card_size - 1)) == 0,
00065 "old must end at card boundary");
00066 assert(card_size >= 512, "card_size must be at least 512");
00067 int bmsize =
00068 (Universe::old_gen.high_boundary - Universe::new_gen.low_boundary)
00069 / card_size;
00070 return AllocateHeap(size + bmsize, "rSet");
00071 }
00072
00073
00074 rSet::rSet(rSet *old, char *start, char *end) {
00075 ShouldNotReachHere();
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 }
00089
00090 char* rSet::scavenge_contents(oldSpace* sp, char* begin, char* limit) {
00091
00092 assert(!*begin, "check for dirty page");
00093
00094
00095
00096 oop* s = oop_for(begin);
00097
00098
00099 if (s >= sp->top()) return begin + 1;
00100
00101 s = sp->object_start(s);
00102
00103 char* end = begin+1;
00104
00105 oop* object_end = NULL;
00106
00107 while (!*end && end < limit) {
00108 while (!*end && end < limit) end++;
00109
00110
00111 oop* e = min(oop_for(end), (oop*)sp->top());
00112
00113 if (e < (oop*)sp->top()) {
00114
00115 object_end = sp->object_start(e);
00116 if (object_end != e) {
00117
00118 int size = as_memOop(object_end)->size();
00119 object_end += size;
00120 }
00121 end = byte_for(object_end);
00122 }
00123 }
00124
00125
00126 for (char* i = begin; i < end; i++) *i = -1;
00127
00128
00129 oop* e = min(oop_for(end), (oop*)sp->top());
00130
00131 while (s < e) {
00132 memOop m = as_memOop(s);
00133 int size = m->scavenge_tenured_contents();
00134 assert(size = m->size(), "just checking");
00135 s += size;
00136 }
00137 return end;
00138 }
00139
00140 void rSet::scavenge_contents(oldSpace* sp) {
00141 char* current_byte = byte_for(sp->bottom());
00142 char* end_byte = byte_for(sp->top());
00143
00144 *(end_byte + 1) = 0;
00145
00146
00147 while (*current_byte) current_byte++;
00148
00149 while (current_byte <= end_byte) {
00150
00151 current_byte = scavenge_contents(sp, current_byte, end_byte);
00152
00153
00154 while (*current_byte) current_byte++;
00155 }
00156 }
00157
00158 void rSet::print_set_for_space(oldSpace* sp) {
00159 char* current_byte = byte_for(sp->bottom());
00160 char* end_byte = byte_for(sp->top());
00161 lprintf("%s: [%#lx, %#lx]\n", sp->name(), current_byte, end_byte);
00162 while (current_byte <= end_byte) {
00163 if (*current_byte) {
00164 lprintf("_");
00165 } else {
00166 lprintf("*");
00167 }
00168 current_byte++;
00169 }
00170 lprintf("\n");
00171 }
00172
00173 int rSet::number_of_dirty_pages_in(oldSpace* sp) {
00174 int count = 0;
00175 char* current_byte = byte_for(sp->bottom());
00176 char* end_byte = byte_for(sp->top());
00177 while (current_byte <= end_byte) {
00178 if (!*current_byte) count++;
00179 current_byte++;
00180 }
00181 return count;
00182 }
00183
00184 class CheckDirtyClosure : public OopClosure {
00185 public:
00186 bool is_dirty;
00187
00188 void clear() {
00189 is_dirty = false;
00190 }
00191
00192 void do_oop(oop* o) {
00193 if ((*o)->is_new()) {
00194 is_dirty = true;
00195
00196
00197
00198
00199
00200
00201
00202 }
00203 }
00204 };
00205
00206 bool rSet::has_page_dirty_objects(oldSpace* sp, char* page) {
00207
00208 oop* s = sp->object_start(oop_for(page));
00209
00210 oop* e = min(oop_for(page+1), (oop*)sp->top());
00211
00212 CheckDirtyClosure blk;
00213
00214 while (s < e) {
00215 memOop m = as_memOop(s);
00216 blk.clear();
00217 m->oop_iterate(&blk);
00218 if (blk.is_dirty) return true;
00219 s += m->size();
00220 }
00221 return false;
00222 }
00223
00224 int rSet::number_of_pages_with_dirty_objects_in(oldSpace* sp) {
00225 int count = 0;
00226 char* current_byte = byte_for(sp->bottom());
00227 char* end_byte = byte_for(sp->top());
00228 while (current_byte <= end_byte) {
00229 if (has_page_dirty_objects(sp, current_byte))
00230 count++;
00231 current_byte++;
00232 }
00233 return count;
00234 }
00235
00236 void rSet::print_set_for_object(memOop obj) {
00237 std->print("Remember set for 0x%lx ", obj);
00238 obj->print_value();
00239 std->cr();
00240 if (obj->is_new()) {
00241 std->print_cr(" object is in new space!");
00242 } else {
00243 std->sp();
00244 char* current_byte = byte_for(obj->addr());
00245 char* end_byte = byte_for(obj->addr() + obj->size());
00246 while (current_byte <= end_byte) {
00247 if (*current_byte) {
00248 std->print("_");
00249 } else {
00250 std->print("*");
00251 }
00252 current_byte++;
00253 }
00254 std->cr();
00255 }
00256 }
00257
00258 bool rSet::is_object_dirty(memOop obj) {
00259 assert(!obj->is_new(), "just checking");
00260 char* current_byte = byte_for(obj->addr());
00261 char* end_byte = byte_for(obj->addr() + obj->size());
00262 while (current_byte <= end_byte) {
00263 if (*current_byte == 0) return true;
00264 current_byte++;
00265 }
00266 return false;
00267 }
00268
00269 void rSet::clear(char *start, char *end) {
00270 int* from = (int*) start;
00271 int count = (int*) end - from;
00272 set_words(from, count, AllBits);
00273 }
00274
00275 bool rSet::verify(bool postScavenge) {
00276 return true;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 const int lim_0 = markOopDesc::max_age;
00289 const int lim_1 = (1 << 8);
00290 const int lim_2 = lim_1 + (1 << 8);
00291 const int lim_3 = lim_2 + (1 << 16);
00292
00293 void rSet::set_size(memOop obj, int size) {
00294 unsigned char* p = (unsigned char*) byte_for(obj->addr());
00295 assert(size >= lim_0, "size must be >= max_age");
00296 if (size < lim_1) {
00297 *p = (unsigned char) (size - lim_0);
00298 } else if (size < lim_2) {
00299 *p++ = lim_0 + 2;
00300 *p = (unsigned char) (size - lim_1);
00301 } else if (size < lim_3) {
00302 *p++ = lim_0 + 3;
00303 *(unsigned short*)p = (unsigned short) (size - lim_2);
00304 } else {
00305 *p++ = lim_0 + 4;
00306 *(unsigned int*)p = (unsigned int) (size - lim_3);
00307 }
00308 }
00309
00310 int rSet::get_size(memOop obj) {
00311 unsigned char* p = (unsigned char*) byte_for(obj->addr());
00312 unsigned char h = *p++;
00313 if (h <= lim_0 + 1) return h + lim_0;
00314 if (h == lim_0 + 2) return (*(unsigned char*) p) + lim_1;
00315 if (h == lim_0 + 3) return (*(unsigned short*) p) + lim_2;
00316 if (h == lim_0 + 4) return (*(unsigned int*) p) + lim_3;
00317 ShouldNotReachHere();
00318 return 0;
00319 }
00320
00321
00322 void rSet::fixup(char *start, char *end) {
00323 if (end > high_boundary) {
00324 Universe::remembered_set = new rSet(this, start, end);
00325 } else {
00326 clear(byte_for(start), byte_for(end));
00327 }
00328 }