equal
deleted
inserted
replaced
332 }; |
332 }; |
333 |
333 |
334 |
334 |
335 // Iterator to iterate over nmethods in the CodeCache. |
335 // Iterator to iterate over nmethods in the CodeCache. |
336 template <class T, class Filter> class CodeBlobIterator : public StackObj { |
336 template <class T, class Filter> class CodeBlobIterator : public StackObj { |
|
337 public: |
|
338 enum LivenessFilter { all_blobs, only_alive, only_alive_and_not_unloading }; |
|
339 |
337 private: |
340 private: |
338 CodeBlob* _code_blob; // Current CodeBlob |
341 CodeBlob* _code_blob; // Current CodeBlob |
339 GrowableArrayIterator<CodeHeap*> _heap; |
342 GrowableArrayIterator<CodeHeap*> _heap; |
340 GrowableArrayIterator<CodeHeap*> _end; |
343 GrowableArrayIterator<CodeHeap*> _end; |
|
344 bool _only_alive; |
|
345 bool _only_not_unloading; |
341 |
346 |
342 public: |
347 public: |
343 CodeBlobIterator(T* nm = NULL) { |
348 CodeBlobIterator(LivenessFilter filter, T* nm = NULL) |
|
349 : _only_alive(filter == only_alive || filter == only_alive_and_not_unloading), |
|
350 _only_not_unloading(filter == only_alive_and_not_unloading) |
|
351 { |
344 if (Filter::heaps() == NULL) { |
352 if (Filter::heaps() == NULL) { |
345 return; |
353 return; |
346 } |
354 } |
347 _heap = Filter::heaps()->begin(); |
355 _heap = Filter::heaps()->begin(); |
348 _end = Filter::heaps()->end(); |
356 _end = Filter::heaps()->end(); |
358 |
366 |
359 // Advance iterator to next blob |
367 // Advance iterator to next blob |
360 bool next() { |
368 bool next() { |
361 assert_locked_or_safepoint(CodeCache_lock); |
369 assert_locked_or_safepoint(CodeCache_lock); |
362 |
370 |
363 bool result = next_blob(); |
371 for (;;) { |
364 while (!result && _heap != _end) { |
372 // Walk through heaps as required |
365 // Advance to next code heap of segmented code cache |
373 if (!next_blob()) { |
366 if (++_heap == _end) { |
374 if (_heap == _end) { |
367 break; |
375 return false; |
|
376 } |
|
377 ++_heap; |
|
378 continue; |
368 } |
379 } |
369 result = next_blob(); |
380 |
370 } |
381 // Filter is_alive as required |
371 |
382 if (_only_alive && !_code_blob->is_alive()) { |
372 return result; |
383 continue; |
373 } |
384 } |
374 |
385 |
375 // Advance iterator to next alive blob |
386 // Filter is_unloading as required |
376 bool next_alive() { |
387 if (_only_not_unloading) { |
377 bool result = next(); |
388 CompiledMethod* cm = _code_blob->as_compiled_method_or_null(); |
378 while(result && !_code_blob->is_alive()) { |
389 if (cm != NULL && cm->is_unloading()) { |
379 result = next(); |
390 continue; |
380 } |
391 } |
381 return result; |
392 } |
382 } |
393 |
383 |
394 return true; |
384 bool end() const { return _code_blob == NULL; } |
395 } |
385 T* method() const { return (T*)_code_blob; } |
396 } |
|
397 |
|
398 bool end() const { return _code_blob == NULL; } |
|
399 T* method() const { return (T*)_code_blob; } |
386 |
400 |
387 private: |
401 private: |
388 |
402 |
389 // Advance iterator to the next blob in the current code heap |
403 // Advance iterator to the next blob in the current code heap |
390 bool next_blob() { |
404 bool next_blob() { |
420 struct NMethodFilter { |
434 struct NMethodFilter { |
421 static bool apply(CodeBlob* cb) { return cb->is_nmethod(); } |
435 static bool apply(CodeBlob* cb) { return cb->is_nmethod(); } |
422 static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::nmethod_heaps(); } |
436 static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::nmethod_heaps(); } |
423 }; |
437 }; |
424 |
438 |
425 |
|
426 typedef CodeBlobIterator<CompiledMethod, CompiledMethodFilter> CompiledMethodIterator; |
439 typedef CodeBlobIterator<CompiledMethod, CompiledMethodFilter> CompiledMethodIterator; |
427 typedef CodeBlobIterator<nmethod, NMethodFilter> NMethodIterator; |
440 typedef CodeBlobIterator<nmethod, NMethodFilter> NMethodIterator; |
428 |
441 |
429 #endif // SHARE_VM_CODE_CODECACHE_HPP |
442 #endif // SHARE_VM_CODE_CODECACHE_HPP |