Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/metadataOnStackMark.cpp @ 20619:b12a2a9b05ca
8056240: Investigate increased GC remark time after class unloading changes in CRM Fuse
Reviewed-by: mgerdin, coleenp, bdelsart
author | stefank |
---|---|
date | Thu, 02 Oct 2014 10:55:36 +0200 |
parents | 2c6ef90f030a |
children | 76af33d4d504 |
comparison
equal
deleted
inserted
replaced
20618:7024b693c8f9 | 20619:b12a2a9b05ca |
---|---|
29 #include "oops/metadata.hpp" | 29 #include "oops/metadata.hpp" |
30 #include "prims/jvmtiImpl.hpp" | 30 #include "prims/jvmtiImpl.hpp" |
31 #include "runtime/synchronizer.hpp" | 31 #include "runtime/synchronizer.hpp" |
32 #include "runtime/thread.hpp" | 32 #include "runtime/thread.hpp" |
33 #include "services/threadService.hpp" | 33 #include "services/threadService.hpp" |
34 #include "utilities/growableArray.hpp" | 34 #include "utilities/chunkedList.hpp" |
35 | 35 |
36 volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL; | |
37 volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL; | |
36 | 38 |
37 // Keep track of marked on-stack metadata so it can be cleared. | |
38 GrowableArray<Metadata*>* _marked_objects = NULL; | |
39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) | 39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) |
40 | 40 |
41 // Walk metadata on the stack and mark it so that redefinition doesn't delete | 41 // Walk metadata on the stack and mark it so that redefinition doesn't delete |
42 // it. Class unloading also walks the previous versions and might try to | 42 // it. Class unloading also walks the previous versions and might try to |
43 // delete it, so this class is used by class unloading also. | 43 // delete it, so this class is used by class unloading also. |
44 MetadataOnStackMark::MetadataOnStackMark() { | 44 MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { |
45 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); | 45 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); |
46 assert(_used_buffers == NULL, "sanity check"); | |
46 NOT_PRODUCT(_is_active = true;) | 47 NOT_PRODUCT(_is_active = true;) |
47 if (_marked_objects == NULL) { | |
48 _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true); | |
49 } | |
50 | 48 |
51 Threads::metadata_do(Metadata::mark_on_stack); | 49 Threads::metadata_do(Metadata::mark_on_stack); |
52 if (JvmtiExport::has_redefined_a_class()) { | 50 if (visit_code_cache) { |
53 CodeCache::alive_nmethods_do(nmethod::mark_on_stack); | 51 CodeCache::alive_nmethods_do(nmethod::mark_on_stack); |
54 } | 52 } |
55 CompileBroker::mark_on_stack(); | 53 CompileBroker::mark_on_stack(); |
56 JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack); | 54 JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack); |
57 ThreadService::metadata_do(Metadata::mark_on_stack); | 55 ThreadService::metadata_do(Metadata::mark_on_stack); |
60 MetadataOnStackMark::~MetadataOnStackMark() { | 58 MetadataOnStackMark::~MetadataOnStackMark() { |
61 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); | 59 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); |
62 // Unmark everything that was marked. Can't do the same walk because | 60 // Unmark everything that was marked. Can't do the same walk because |
63 // redefine classes messes up the code cache so the set of methods | 61 // redefine classes messes up the code cache so the set of methods |
64 // might not be the same. | 62 // might not be the same. |
65 for (int i = 0; i< _marked_objects->length(); i++) { | 63 |
66 _marked_objects->at(i)->set_on_stack(false); | 64 retire_buffer_for_thread(Thread::current()); |
65 | |
66 MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers); | |
67 while (buffer != NULL) { | |
68 // Clear on stack state for all metadata. | |
69 size_t size = buffer->size(); | |
70 for (size_t i = 0; i < size; i++) { | |
71 Metadata* md = buffer->at(i); | |
72 md->set_on_stack(false); | |
73 } | |
74 | |
75 MetadataOnStackBuffer* next = buffer->next_used(); | |
76 | |
77 // Move the buffer to the free list. | |
78 buffer->clear(); | |
79 buffer->set_next_used(NULL); | |
80 buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers)); | |
81 _free_buffers = buffer; | |
82 | |
83 // Step to next used buffer. | |
84 buffer = next; | |
67 } | 85 } |
68 _marked_objects->clear(); // reuse growable array for next time. | 86 |
87 _used_buffers = NULL; | |
88 | |
69 NOT_PRODUCT(_is_active = false;) | 89 NOT_PRODUCT(_is_active = false;) |
70 } | 90 } |
71 | 91 |
92 void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) { | |
93 if (buffer == NULL) { | |
94 return; | |
95 } | |
96 | |
97 MetadataOnStackBuffer* old_head; | |
98 | |
99 do { | |
100 old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers); | |
101 buffer->set_next_used(old_head); | |
102 } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head); | |
103 } | |
104 | |
105 void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) { | |
106 retire_buffer(thread->metadata_on_stack_buffer()); | |
107 thread->set_metadata_on_stack_buffer(NULL); | |
108 } | |
109 | |
110 bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) { | |
111 return thread->metadata_on_stack_buffer() != NULL; | |
112 } | |
113 | |
114 MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() { | |
115 MetadataOnStackBuffer* allocated; | |
116 MetadataOnStackBuffer* new_head; | |
117 | |
118 do { | |
119 allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers); | |
120 if (allocated == NULL) { | |
121 break; | |
122 } | |
123 new_head = allocated->next_free(); | |
124 } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated); | |
125 | |
126 if (allocated == NULL) { | |
127 allocated = new MetadataOnStackBuffer(); | |
128 } | |
129 | |
130 assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated))); | |
131 | |
132 return allocated; | |
133 } | |
134 | |
72 // Record which objects are marked so we can unmark the same objects. | 135 // Record which objects are marked so we can unmark the same objects. |
73 void MetadataOnStackMark::record(Metadata* m) { | 136 void MetadataOnStackMark::record(Metadata* m, Thread* thread) { |
74 assert(_is_active, "metadata on stack marking is active"); | 137 assert(_is_active, "metadata on stack marking is active"); |
75 _marked_objects->push(m); | 138 |
139 MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer(); | |
140 | |
141 if (buffer != NULL && buffer->is_full()) { | |
142 retire_buffer(buffer); | |
143 buffer = NULL; | |
144 } | |
145 | |
146 if (buffer == NULL) { | |
147 buffer = allocate_buffer(); | |
148 thread->set_metadata_on_stack_buffer(buffer); | |
149 } | |
150 | |
151 buffer->push(m); | |
76 } | 152 } |