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()); |
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) { |