264 } else {
265 os->print("%s", type2name(ss.type()));
266 }
267 first = false;
268 }
269 }
270
271 // Increment refcount while checking for zero. If the Symbol's refcount becomes zero
272 // a thread could be concurrently removing the Symbol. This is used during SymbolTable
273 // lookup to avoid reviving a dead Symbol.
274 bool Symbol::try_increment_refcount() {
275 uint32_t found = _length_and_refcount;
276 while (true) {
277 uint32_t old_value = found;
278 int refc = extract_refcount(old_value);
279 if (refc == PERM_REFCOUNT) {
280 return true; // sticky max or created permanent
281 } else if (refc == 0) {
282 return false; // dead, can't revive.
283 } else {
284 found = Atomic::cmpxchg(old_value + 1, &_length_and_refcount, old_value);
285 if (found == old_value) {
286 return true; // successfully updated.
287 }
288 // refcount changed, try again.
289 }
290 }
291 }
292
293 // The increment_refcount() is called when not doing lookup. It is assumed that you
294 // have a symbol with a non-zero refcount and it can't become zero while referenced by
295 // this caller.
296 void Symbol::increment_refcount() {
297 if (!try_increment_refcount()) {
298 #ifdef ASSERT
299 print();
300 fatal("refcount has gone to zero");
301 #endif
302 }
303 #ifndef PRODUCT
304 if (refcount() != PERM_REFCOUNT) { // not a permanent symbol
307 #endif
308 }
309
310 // Decrement refcount potentially while racing increment, so we need
311 // to check the value after attempting to decrement so that if another
312 // thread increments to PERM_REFCOUNT the value is not decremented.
313 void Symbol::decrement_refcount() {
314 uint32_t found = _length_and_refcount;
315 while (true) {
316 uint32_t old_value = found;
317 int refc = extract_refcount(old_value);
318 if (refc == PERM_REFCOUNT) {
319 return; // refcount is permanent, permanent is sticky
320 } else if (refc == 0) {
321 #ifdef ASSERT
322 print();
323 fatal("refcount underflow");
324 #endif
325 return;
326 } else {
327 found = Atomic::cmpxchg(old_value - 1, &_length_and_refcount, old_value);
328 if (found == old_value) {
329 return; // successfully updated.
330 }
331 // refcount changed, try again.
332 }
333 }
334 }
335
336 void Symbol::make_permanent() {
337 uint32_t found = _length_and_refcount;
338 while (true) {
339 uint32_t old_value = found;
340 int refc = extract_refcount(old_value);
341 if (refc == PERM_REFCOUNT) {
342 return; // refcount is permanent, permanent is sticky
343 } else if (refc == 0) {
344 #ifdef ASSERT
345 print();
346 fatal("refcount underflow");
347 #endif
348 return;
349 } else {
350 int len = extract_length(old_value);
351 found = Atomic::cmpxchg(pack_length_and_refcount(len, PERM_REFCOUNT), &_length_and_refcount, old_value);
352 if (found == old_value) {
353 return; // successfully updated.
354 }
355 // refcount changed, try again.
356 }
357 }
358 }
359
360 void Symbol::metaspace_pointers_do(MetaspaceClosure* it) {
361 if (log_is_enabled(Trace, cds)) {
362 LogStream trace_stream(Log(cds)::trace());
363 trace_stream.print("Iter(Symbol): %p ", this);
364 print_value_on(&trace_stream);
365 trace_stream.cr();
366 }
367 }
368
369 void Symbol::print_on(outputStream* st) const {
370 st->print("Symbol: '");
371 print_symbol_on(st);
|
264 } else {
265 os->print("%s", type2name(ss.type()));
266 }
267 first = false;
268 }
269 }
270
271 // Increment refcount while checking for zero. If the Symbol's refcount becomes zero
272 // a thread could be concurrently removing the Symbol. This is used during SymbolTable
273 // lookup to avoid reviving a dead Symbol.
274 bool Symbol::try_increment_refcount() {
275 uint32_t found = _length_and_refcount;
276 while (true) {
277 uint32_t old_value = found;
278 int refc = extract_refcount(old_value);
279 if (refc == PERM_REFCOUNT) {
280 return true; // sticky max or created permanent
281 } else if (refc == 0) {
282 return false; // dead, can't revive.
283 } else {
284 found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value + 1);
285 if (found == old_value) {
286 return true; // successfully updated.
287 }
288 // refcount changed, try again.
289 }
290 }
291 }
292
293 // The increment_refcount() is called when not doing lookup. It is assumed that you
294 // have a symbol with a non-zero refcount and it can't become zero while referenced by
295 // this caller.
296 void Symbol::increment_refcount() {
297 if (!try_increment_refcount()) {
298 #ifdef ASSERT
299 print();
300 fatal("refcount has gone to zero");
301 #endif
302 }
303 #ifndef PRODUCT
304 if (refcount() != PERM_REFCOUNT) { // not a permanent symbol
307 #endif
308 }
309
310 // Decrement refcount potentially while racing increment, so we need
311 // to check the value after attempting to decrement so that if another
312 // thread increments to PERM_REFCOUNT the value is not decremented.
313 void Symbol::decrement_refcount() {
314 uint32_t found = _length_and_refcount;
315 while (true) {
316 uint32_t old_value = found;
317 int refc = extract_refcount(old_value);
318 if (refc == PERM_REFCOUNT) {
319 return; // refcount is permanent, permanent is sticky
320 } else if (refc == 0) {
321 #ifdef ASSERT
322 print();
323 fatal("refcount underflow");
324 #endif
325 return;
326 } else {
327 found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value - 1);
328 if (found == old_value) {
329 return; // successfully updated.
330 }
331 // refcount changed, try again.
332 }
333 }
334 }
335
336 void Symbol::make_permanent() {
337 uint32_t found = _length_and_refcount;
338 while (true) {
339 uint32_t old_value = found;
340 int refc = extract_refcount(old_value);
341 if (refc == PERM_REFCOUNT) {
342 return; // refcount is permanent, permanent is sticky
343 } else if (refc == 0) {
344 #ifdef ASSERT
345 print();
346 fatal("refcount underflow");
347 #endif
348 return;
349 } else {
350 int len = extract_length(old_value);
351 found = Atomic::cmpxchg(&_length_and_refcount, old_value, pack_length_and_refcount(len, PERM_REFCOUNT));
352 if (found == old_value) {
353 return; // successfully updated.
354 }
355 // refcount changed, try again.
356 }
357 }
358 }
359
360 void Symbol::metaspace_pointers_do(MetaspaceClosure* it) {
361 if (log_is_enabled(Trace, cds)) {
362 LogStream trace_stream(Log(cds)::trace());
363 trace_stream.print("Iter(Symbol): %p ", this);
364 print_value_on(&trace_stream);
365 trace_stream.cr();
366 }
367 }
368
369 void Symbol::print_on(outputStream* st) const {
370 st->print("Symbol: '");
371 print_symbol_on(st);
|