Mercurial > hg > truffle
comparison src/share/vm/oops/typeArrayKlass.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | fc9d8850ab8b |
children | 86af3dacab81 d8ce2825b193 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "classfile/symbolTable.hpp" | |
26 #include "classfile/systemDictionary.hpp" | 27 #include "classfile/systemDictionary.hpp" |
27 #include "classfile/vmSymbols.hpp" | 28 #include "classfile/vmSymbols.hpp" |
28 #include "gc_interface/collectedHeap.hpp" | 29 #include "gc_interface/collectedHeap.hpp" |
29 #include "gc_interface/collectedHeap.inline.hpp" | 30 #include "gc_interface/collectedHeap.inline.hpp" |
31 #include "memory/metadataFactory.hpp" | |
30 #include "memory/resourceArea.hpp" | 32 #include "memory/resourceArea.hpp" |
31 #include "memory/universe.hpp" | 33 #include "memory/universe.hpp" |
32 #include "memory/universe.inline.hpp" | 34 #include "memory/universe.inline.hpp" |
33 #include "oops/instanceKlass.hpp" | 35 #include "oops/instanceKlass.hpp" |
34 #include "oops/klassOop.hpp" | 36 #include "oops/klass.inline.hpp" |
35 #include "oops/objArrayKlassKlass.hpp" | 37 #include "oops/objArrayKlass.hpp" |
36 #include "oops/oop.inline.hpp" | 38 #include "oops/oop.inline.hpp" |
37 #include "oops/typeArrayKlass.hpp" | 39 #include "oops/typeArrayKlass.hpp" |
38 #include "oops/typeArrayOop.hpp" | 40 #include "oops/typeArrayOop.hpp" |
39 #include "runtime/handles.inline.hpp" | 41 #include "runtime/handles.inline.hpp" |
40 | 42 |
41 bool typeArrayKlass::compute_is_subtype_of(klassOop k) { | 43 bool typeArrayKlass::compute_is_subtype_of(Klass* k) { |
42 if (!k->klass_part()->oop_is_typeArray()) { | 44 if (!k->oop_is_typeArray()) { |
43 return arrayKlass::compute_is_subtype_of(k); | 45 return arrayKlass::compute_is_subtype_of(k); |
44 } | 46 } |
45 | 47 |
46 typeArrayKlass* tak = typeArrayKlass::cast(k); | 48 typeArrayKlass* tak = typeArrayKlass::cast(k); |
47 if (dimension() != tak->dimension()) return false; | 49 if (dimension() != tak->dimension()) return false; |
48 | 50 |
49 return element_type() == tak->element_type(); | 51 return element_type() == tak->element_type(); |
50 } | 52 } |
51 | 53 |
52 klassOop typeArrayKlass::create_klass(BasicType type, int scale, | 54 typeArrayKlass* typeArrayKlass::create_klass(BasicType type, |
53 const char* name_str, TRAPS) { | 55 const char* name_str, TRAPS) { |
54 typeArrayKlass o; | |
55 | |
56 Symbol* sym = NULL; | 56 Symbol* sym = NULL; |
57 if (name_str != NULL) { | 57 if (name_str != NULL) { |
58 sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL); | 58 sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL); |
59 } | 59 } |
60 KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj()); | 60 |
61 | 61 ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data(); |
62 arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL); | 62 |
63 typeArrayKlass* ak = typeArrayKlass::cast(k()); | 63 typeArrayKlass* ak = typeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL); |
64 ak->set_name(sym); | 64 |
65 ak->set_layout_helper(array_layout_helper(type)); | 65 // Add all classes to our internal class loader list here, |
66 assert(scale == (1 << ak->log2_element_size()), "scale must check out"); | 66 // including classes in the bootstrap (NULL) class loader. |
67 assert(ak->oop_is_javaArray(), "sanity"); | 67 // GC walks these as strong roots. |
68 assert(ak->oop_is_typeArray(), "sanity"); | 68 null_loader_data->add_class(ak); |
69 ak->set_max_length(arrayOopDesc::max_array_length(type)); | |
70 assert(k()->size() > header_size(), "bad size"); | |
71 | 69 |
72 // Call complete_create_array_klass after all instance variables have been initialized. | 70 // Call complete_create_array_klass after all instance variables have been initialized. |
73 KlassHandle super (THREAD, k->super()); | 71 complete_create_array_klass(ak, ak->super(), CHECK_NULL); |
74 complete_create_array_klass(k, super, CHECK_NULL); | 72 |
75 | 73 return ak; |
76 return k(); | 74 } |
75 | |
76 typeArrayKlass* typeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) { | |
77 assert(typeArrayKlass::header_size() <= InstanceKlass::header_size(), | |
78 "array klasses must be same size as InstanceKlass"); | |
79 | |
80 int size = arrayKlass::static_size(typeArrayKlass::header_size()); | |
81 | |
82 return new (loader_data, size, THREAD) typeArrayKlass(type, name); | |
83 } | |
84 | |
85 typeArrayKlass::typeArrayKlass(BasicType type, Symbol* name) : arrayKlass(name) { | |
86 set_layout_helper(array_layout_helper(type)); | |
87 assert(oop_is_array(), "sanity"); | |
88 assert(oop_is_typeArray(), "sanity"); | |
89 | |
90 set_max_length(arrayOopDesc::max_array_length(type)); | |
91 assert(size() >= typeArrayKlass::header_size(), "bad size"); | |
92 | |
93 set_class_loader_data(ClassLoaderData::the_null_class_loader_data()); | |
77 } | 94 } |
78 | 95 |
79 typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { | 96 typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { |
80 assert(log2_element_size() >= 0, "bad scale"); | 97 assert(log2_element_size() >= 0, "bad scale"); |
81 if (length >= 0) { | 98 if (length >= 0) { |
82 if (length <= max_length()) { | 99 if (length <= max_length()) { |
83 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); | 100 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); |
84 KlassHandle h_k(THREAD, as_klassOop()); | 101 KlassHandle h_k(THREAD, this); |
85 typeArrayOop t; | 102 typeArrayOop t; |
86 CollectedHeap* ch = Universe::heap(); | 103 CollectedHeap* ch = Universe::heap(); |
87 if (do_zero) { | 104 if (do_zero) { |
88 t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); | 105 t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); |
89 } else { | 106 } else { |
90 t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL); | 107 t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL); |
91 } | 108 } |
92 assert(t->is_parsable(), "Don't publish unless parsable"); | |
93 return t; | 109 return t; |
94 } else { | 110 } else { |
95 report_java_out_of_memory("Requested array size exceeds VM limit"); | 111 report_java_out_of_memory("Requested array size exceeds VM limit"); |
96 JvmtiExport::post_array_size_exhausted(); | 112 JvmtiExport::post_array_size_exhausted(); |
97 THROW_OOP_0(Universe::out_of_memory_error_array_size()); | 113 THROW_OOP_0(Universe::out_of_memory_error_array_size()); |
99 } else { | 115 } else { |
100 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | 116 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); |
101 } | 117 } |
102 } | 118 } |
103 | 119 |
104 typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) { | |
105 if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | |
106 int size = typeArrayOopDesc::object_size(layout_helper(), length); | |
107 KlassHandle h_k(THREAD, as_klassOop()); | |
108 typeArrayOop t = (typeArrayOop) | |
109 CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL); | |
110 assert(t->is_parsable(), "Can't publish until parsable"); | |
111 return t; | |
112 } | |
113 | |
114 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { | 120 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { |
115 // For typeArrays this is only called for the last dimension | 121 // For typeArrays this is only called for the last dimension |
116 assert(rank == 1, "just checking"); | 122 assert(rank == 1, "just checking"); |
117 int length = *last_size; | 123 int length = *last_size; |
118 return allocate(length, THREAD); | 124 return allocate(length, THREAD); |
148 Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); | 154 Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); |
149 } | 155 } |
150 | 156 |
151 | 157 |
152 // create a klass of array holding typeArrays | 158 // create a klass of array holding typeArrays |
153 klassOop typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { | 159 Klass* typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { |
154 typeArrayKlassHandle h_this(THREAD, as_klassOop()); | 160 int dim = dimension(); |
155 return array_klass_impl(h_this, or_null, n, THREAD); | 161 assert(dim <= n, "check order of chain"); |
156 } | 162 if (dim == n) |
157 | 163 return this; |
158 klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_null, int n, TRAPS) { | 164 |
159 int dimension = h_this->dimension(); | 165 if (higher_dimension() == NULL) { |
160 assert(dimension <= n, "check order of chain"); | |
161 if (dimension == n) | |
162 return h_this(); | |
163 | |
164 objArrayKlassHandle h_ak(THREAD, h_this->higher_dimension()); | |
165 if (h_ak.is_null()) { | |
166 if (or_null) return NULL; | 166 if (or_null) return NULL; |
167 | 167 |
168 ResourceMark rm; | 168 ResourceMark rm; |
169 JavaThread *jt = (JavaThread *)THREAD; | 169 JavaThread *jt = (JavaThread *)THREAD; |
170 { | 170 { |
171 MutexLocker mc(Compile_lock, THREAD); // for vtables | 171 MutexLocker mc(Compile_lock, THREAD); // for vtables |
172 // Atomic create higher dimension and link into list | 172 // Atomic create higher dimension and link into list |
173 MutexLocker mu(MultiArray_lock, THREAD); | 173 MutexLocker mu(MultiArray_lock, THREAD); |
174 | 174 |
175 h_ak = objArrayKlassHandle(THREAD, h_this->higher_dimension()); | 175 if (higher_dimension() == NULL) { |
176 if (h_ak.is_null()) { | 176 Klass* oak = objArrayKlass::allocate_objArray_klass( |
177 klassOop oak = objArrayKlassKlass::cast( | 177 class_loader_data(), dim + 1, this, CHECK_NULL); |
178 Universe::objArrayKlassKlassObj())->allocate_objArray_klass( | 178 objArrayKlass* h_ak = objArrayKlass::cast(oak); |
179 dimension + 1, h_this, CHECK_NULL); | 179 h_ak->set_lower_dimension(this); |
180 h_ak = objArrayKlassHandle(THREAD, oak); | |
181 h_ak->set_lower_dimension(h_this()); | |
182 OrderAccess::storestore(); | 180 OrderAccess::storestore(); |
183 h_this->set_higher_dimension(h_ak()); | 181 set_higher_dimension(h_ak); |
184 assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); | 182 assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); |
185 } | 183 } |
186 } | 184 } |
187 } else { | 185 } else { |
188 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); | 186 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); |
189 } | 187 } |
188 objArrayKlass* h_ak = objArrayKlass::cast(higher_dimension()); | |
190 if (or_null) { | 189 if (or_null) { |
191 return h_ak->array_klass_or_null(n); | 190 return h_ak->array_klass_or_null(n); |
192 } | 191 } |
193 return h_ak->array_klass(n, CHECK_NULL); | 192 return h_ak->array_klass(n, CHECK_NULL); |
194 } | 193 } |
195 | 194 |
196 klassOop typeArrayKlass::array_klass_impl(bool or_null, TRAPS) { | 195 Klass* typeArrayKlass::array_klass_impl(bool or_null, TRAPS) { |
197 return array_klass_impl(or_null, dimension() + 1, THREAD); | 196 return array_klass_impl(or_null, dimension() + 1, THREAD); |
198 } | 197 } |
199 | 198 |
200 int typeArrayKlass::oop_size(oop obj) const { | 199 int typeArrayKlass::oop_size(oop obj) const { |
201 assert(obj->is_typeArray(),"must be a type array"); | 200 assert(obj->is_typeArray(),"must be a type array"); |
223 // Performance tweak: We skip iterating over the klass pointer since we | 222 // Performance tweak: We skip iterating over the klass pointer since we |
224 // know that Universe::typeArrayKlass never moves. | 223 // know that Universe::typeArrayKlass never moves. |
225 return t->object_size(); | 224 return t->object_size(); |
226 } | 225 } |
227 | 226 |
228 int typeArrayKlass::oop_oop_iterate(oop obj, OopClosure* blk) { | 227 int typeArrayKlass::oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { |
229 assert(obj->is_typeArray(),"must be a type array"); | 228 assert(obj->is_typeArray(),"must be a type array"); |
230 typeArrayOop t = typeArrayOop(obj); | 229 typeArrayOop t = typeArrayOop(obj); |
231 // Performance tweak: We skip iterating over the klass pointer since we | 230 // Performance tweak: We skip iterating over the klass pointer since we |
232 // know that Universe::typeArrayKlass never moves. | 231 // know that Universe::typeArrayKlass never moves. |
233 return t->object_size(); | 232 return t->object_size(); |
234 } | 233 } |
235 | 234 |
236 int typeArrayKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) { | 235 int typeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) { |
237 assert(obj->is_typeArray(),"must be a type array"); | 236 assert(obj->is_typeArray(),"must be a type array"); |
238 typeArrayOop t = typeArrayOop(obj); | 237 typeArrayOop t = typeArrayOop(obj); |
239 // Performance tweak: We skip iterating over the klass pointer since we | 238 // Performance tweak: We skip iterating over the klass pointer since we |
240 // know that Universe::typeArrayKlass never moves. | 239 // know that Universe::typeArrayKlass never moves. |
241 return t->object_size(); | 240 return t->object_size(); |
242 } | 241 } |
243 | 242 |
244 #ifndef SERIALGC | 243 #ifndef SERIALGC |
245 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { | 244 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { |
245 ShouldNotReachHere(); | |
246 assert(obj->is_typeArray(),"must be a type array"); | 246 assert(obj->is_typeArray(),"must be a type array"); |
247 } | 247 } |
248 | 248 |
249 int | 249 int |
250 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { | 250 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { |
271 default: ShouldNotReachHere(); | 271 default: ShouldNotReachHere(); |
272 } | 272 } |
273 return NULL; | 273 return NULL; |
274 } | 274 } |
275 | 275 |
276 | |
277 // Printing | |
278 | |
279 void typeArrayKlass::print_on(outputStream* st) const { | |
276 #ifndef PRODUCT | 280 #ifndef PRODUCT |
277 // Printing | 281 assert(is_klass(), "must be klass"); |
282 print_value_on(st); | |
283 Klass::print_on(st); | |
284 #endif //PRODUCT | |
285 } | |
286 | |
287 void typeArrayKlass::print_value_on(outputStream* st) const { | |
288 assert(is_klass(), "must be klass"); | |
289 st->print("{type array "); | |
290 switch (element_type()) { | |
291 case T_BOOLEAN: st->print("bool"); break; | |
292 case T_CHAR: st->print("char"); break; | |
293 case T_FLOAT: st->print("float"); break; | |
294 case T_DOUBLE: st->print("double"); break; | |
295 case T_BYTE: st->print("byte"); break; | |
296 case T_SHORT: st->print("short"); break; | |
297 case T_INT: st->print("int"); break; | |
298 case T_LONG: st->print("long"); break; | |
299 default: ShouldNotReachHere(); | |
300 } | |
301 st->print("}"); | |
302 } | |
303 | |
304 #ifndef PRODUCT | |
278 | 305 |
279 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) { | 306 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) { |
280 for (int index = 0; index < print_len; index++) { | 307 for (int index = 0; index < print_len; index++) { |
281 st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true"); | 308 st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true"); |
282 } | 309 } |