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 }