38 #include "oops/oop.inline.hpp" |
38 #include "oops/oop.inline.hpp" |
39 #include "oops/typeArrayKlass.hpp" |
39 #include "oops/typeArrayKlass.hpp" |
40 #include "oops/typeArrayOop.hpp" |
40 #include "oops/typeArrayOop.hpp" |
41 #include "runtime/handles.inline.hpp" |
41 #include "runtime/handles.inline.hpp" |
42 |
42 |
43 bool typeArrayKlass::compute_is_subtype_of(Klass* k) { |
43 bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { |
44 if (!k->oop_is_typeArray()) { |
44 if (!k->oop_is_typeArray()) { |
45 return arrayKlass::compute_is_subtype_of(k); |
45 return ArrayKlass::compute_is_subtype_of(k); |
46 } |
46 } |
47 |
47 |
48 typeArrayKlass* tak = typeArrayKlass::cast(k); |
48 TypeArrayKlass* tak = TypeArrayKlass::cast(k); |
49 if (dimension() != tak->dimension()) return false; |
49 if (dimension() != tak->dimension()) return false; |
50 |
50 |
51 return element_type() == tak->element_type(); |
51 return element_type() == tak->element_type(); |
52 } |
52 } |
53 |
53 |
54 typeArrayKlass* typeArrayKlass::create_klass(BasicType type, |
54 TypeArrayKlass* TypeArrayKlass::create_klass(BasicType type, |
55 const char* name_str, TRAPS) { |
55 const char* name_str, TRAPS) { |
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 |
60 |
61 ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data(); |
61 ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data(); |
62 |
62 |
63 typeArrayKlass* ak = typeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL); |
63 TypeArrayKlass* ak = TypeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL); |
64 |
64 |
65 // Add all classes to our internal class loader list here, |
65 // Add all classes to our internal class loader list here, |
66 // including classes in the bootstrap (NULL) class loader. |
66 // including classes in the bootstrap (NULL) class loader. |
67 // GC walks these as strong roots. |
67 // GC walks these as strong roots. |
68 null_loader_data->add_class(ak); |
68 null_loader_data->add_class(ak); |
71 complete_create_array_klass(ak, ak->super(), CHECK_NULL); |
71 complete_create_array_klass(ak, ak->super(), CHECK_NULL); |
72 |
72 |
73 return ak; |
73 return ak; |
74 } |
74 } |
75 |
75 |
76 typeArrayKlass* typeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) { |
76 TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) { |
77 assert(typeArrayKlass::header_size() <= InstanceKlass::header_size(), |
77 assert(TypeArrayKlass::header_size() <= InstanceKlass::header_size(), |
78 "array klasses must be same size as InstanceKlass"); |
78 "array klasses must be same size as InstanceKlass"); |
79 |
79 |
80 int size = arrayKlass::static_size(typeArrayKlass::header_size()); |
80 int size = ArrayKlass::static_size(TypeArrayKlass::header_size()); |
81 |
81 |
82 return new (loader_data, size, THREAD) typeArrayKlass(type, name); |
82 return new (loader_data, size, THREAD) TypeArrayKlass(type, name); |
83 } |
83 } |
84 |
84 |
85 typeArrayKlass::typeArrayKlass(BasicType type, Symbol* name) : arrayKlass(name) { |
85 TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) { |
86 set_layout_helper(array_layout_helper(type)); |
86 set_layout_helper(array_layout_helper(type)); |
87 assert(oop_is_array(), "sanity"); |
87 assert(oop_is_array(), "sanity"); |
88 assert(oop_is_typeArray(), "sanity"); |
88 assert(oop_is_typeArray(), "sanity"); |
89 |
89 |
90 set_max_length(arrayOopDesc::max_array_length(type)); |
90 set_max_length(arrayOopDesc::max_array_length(type)); |
91 assert(size() >= typeArrayKlass::header_size(), "bad size"); |
91 assert(size() >= TypeArrayKlass::header_size(), "bad size"); |
92 |
92 |
93 set_class_loader_data(ClassLoaderData::the_null_class_loader_data()); |
93 set_class_loader_data(ClassLoaderData::the_null_class_loader_data()); |
94 } |
94 } |
95 |
95 |
96 typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { |
96 typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { |
97 assert(log2_element_size() >= 0, "bad scale"); |
97 assert(log2_element_size() >= 0, "bad scale"); |
98 if (length >= 0) { |
98 if (length >= 0) { |
99 if (length <= max_length()) { |
99 if (length <= max_length()) { |
100 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); |
100 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); |
101 KlassHandle h_k(THREAD, this); |
101 KlassHandle h_k(THREAD, this); |
115 } else { |
115 } else { |
116 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); |
116 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); |
117 } |
117 } |
118 } |
118 } |
119 |
119 |
120 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { |
120 oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { |
121 // For typeArrays this is only called for the last dimension |
121 // For typeArrays this is only called for the last dimension |
122 assert(rank == 1, "just checking"); |
122 assert(rank == 1, "just checking"); |
123 int length = *last_size; |
123 int length = *last_size; |
124 return allocate(length, THREAD); |
124 return allocate(length, THREAD); |
125 } |
125 } |
126 |
126 |
127 |
127 |
128 void typeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) { |
128 void TypeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) { |
129 assert(s->is_typeArray(), "must be type array"); |
129 assert(s->is_typeArray(), "must be type array"); |
130 |
130 |
131 // Check destination |
131 // Check destination |
132 if (!d->is_typeArray() || element_type() != typeArrayKlass::cast(d->klass())->element_type()) { |
132 if (!d->is_typeArray() || element_type() != TypeArrayKlass::cast(d->klass())->element_type()) { |
133 THROW(vmSymbols::java_lang_ArrayStoreException()); |
133 THROW(vmSymbols::java_lang_ArrayStoreException()); |
134 } |
134 } |
135 |
135 |
136 // Check is all offsets and lengths are non negative |
136 // Check is all offsets and lengths are non negative |
137 if (src_pos < 0 || dst_pos < 0 || length < 0) { |
137 if (src_pos < 0 || dst_pos < 0 || length < 0) { |
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 if (higher_dimension() == NULL) { |
175 if (higher_dimension() == NULL) { |
176 Klass* oak = objArrayKlass::allocate_objArray_klass( |
176 Klass* oak = ObjArrayKlass::allocate_objArray_klass( |
177 class_loader_data(), dim + 1, this, CHECK_NULL); |
177 class_loader_data(), dim + 1, this, CHECK_NULL); |
178 objArrayKlass* h_ak = objArrayKlass::cast(oak); |
178 ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak); |
179 h_ak->set_lower_dimension(this); |
179 h_ak->set_lower_dimension(this); |
180 OrderAccess::storestore(); |
180 OrderAccess::storestore(); |
181 set_higher_dimension(h_ak); |
181 set_higher_dimension(h_ak); |
182 assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); |
182 assert(h_ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass"); |
183 } |
183 } |
184 } |
184 } |
185 } else { |
185 } else { |
186 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); |
186 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); |
187 } |
187 } |
188 objArrayKlass* h_ak = objArrayKlass::cast(higher_dimension()); |
188 ObjArrayKlass* h_ak = ObjArrayKlass::cast(higher_dimension()); |
189 if (or_null) { |
189 if (or_null) { |
190 return h_ak->array_klass_or_null(n); |
190 return h_ak->array_klass_or_null(n); |
191 } |
191 } |
192 return h_ak->array_klass(n, CHECK_NULL); |
192 return h_ak->array_klass(n, CHECK_NULL); |
193 } |
193 } |
194 |
194 |
195 Klass* typeArrayKlass::array_klass_impl(bool or_null, TRAPS) { |
195 Klass* TypeArrayKlass::array_klass_impl(bool or_null, TRAPS) { |
196 return array_klass_impl(or_null, dimension() + 1, THREAD); |
196 return array_klass_impl(or_null, dimension() + 1, THREAD); |
197 } |
197 } |
198 |
198 |
199 int typeArrayKlass::oop_size(oop obj) const { |
199 int TypeArrayKlass::oop_size(oop obj) const { |
200 assert(obj->is_typeArray(),"must be a type array"); |
200 assert(obj->is_typeArray(),"must be a type array"); |
201 typeArrayOop t = typeArrayOop(obj); |
201 typeArrayOop t = typeArrayOop(obj); |
202 return t->object_size(); |
202 return t->object_size(); |
203 } |
203 } |
204 |
204 |
205 void typeArrayKlass::oop_follow_contents(oop obj) { |
205 void TypeArrayKlass::oop_follow_contents(oop obj) { |
206 assert(obj->is_typeArray(),"must be a type array"); |
206 assert(obj->is_typeArray(),"must be a type array"); |
207 // Performance tweak: We skip iterating over the klass pointer since we |
207 // Performance tweak: We skip iterating over the klass pointer since we |
208 // know that Universe::typeArrayKlass never moves. |
208 // know that Universe::TypeArrayKlass never moves. |
209 } |
209 } |
210 |
210 |
211 #ifndef SERIALGC |
211 #ifndef SERIALGC |
212 void typeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { |
212 void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { |
213 assert(obj->is_typeArray(),"must be a type array"); |
213 assert(obj->is_typeArray(),"must be a type array"); |
214 // Performance tweak: We skip iterating over the klass pointer since we |
214 // Performance tweak: We skip iterating over the klass pointer since we |
215 // know that Universe::typeArrayKlass never moves. |
215 // know that Universe::TypeArrayKlass never moves. |
216 } |
216 } |
217 #endif // SERIALGC |
217 #endif // SERIALGC |
218 |
218 |
219 int typeArrayKlass::oop_adjust_pointers(oop obj) { |
219 int TypeArrayKlass::oop_adjust_pointers(oop obj) { |
220 assert(obj->is_typeArray(),"must be a type array"); |
220 assert(obj->is_typeArray(),"must be a type array"); |
221 typeArrayOop t = typeArrayOop(obj); |
221 typeArrayOop t = typeArrayOop(obj); |
222 // Performance tweak: We skip iterating over the klass pointer since we |
222 // Performance tweak: We skip iterating over the klass pointer since we |
223 // know that Universe::typeArrayKlass never moves. |
223 // know that Universe::TypeArrayKlass never moves. |
224 return t->object_size(); |
224 return t->object_size(); |
225 } |
225 } |
226 |
226 |
227 int typeArrayKlass::oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { |
227 int TypeArrayKlass::oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { |
228 assert(obj->is_typeArray(),"must be a type array"); |
228 assert(obj->is_typeArray(),"must be a type array"); |
229 typeArrayOop t = typeArrayOop(obj); |
229 typeArrayOop t = typeArrayOop(obj); |
230 // Performance tweak: We skip iterating over the klass pointer since we |
230 // Performance tweak: We skip iterating over the klass pointer since we |
231 // know that Universe::typeArrayKlass never moves. |
231 // know that Universe::TypeArrayKlass never moves. |
232 return t->object_size(); |
232 return t->object_size(); |
233 } |
233 } |
234 |
234 |
235 int typeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) { |
235 int TypeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) { |
236 assert(obj->is_typeArray(),"must be a type array"); |
236 assert(obj->is_typeArray(),"must be a type array"); |
237 typeArrayOop t = typeArrayOop(obj); |
237 typeArrayOop t = typeArrayOop(obj); |
238 // Performance tweak: We skip iterating over the klass pointer since we |
238 // Performance tweak: We skip iterating over the klass pointer since we |
239 // know that Universe::typeArrayKlass never moves. |
239 // know that Universe::TypeArrayKlass never moves. |
240 return t->object_size(); |
240 return t->object_size(); |
241 } |
241 } |
242 |
242 |
243 #ifndef SERIALGC |
243 #ifndef SERIALGC |
244 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { |
244 void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { |
245 ShouldNotReachHere(); |
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) { |
251 assert(obj->is_typeArray(),"must be a type array"); |
251 assert(obj->is_typeArray(),"must be a type array"); |
252 return typeArrayOop(obj)->object_size(); |
252 return typeArrayOop(obj)->object_size(); |
253 } |
253 } |
254 #endif // SERIALGC |
254 #endif // SERIALGC |
255 |
255 |
256 void typeArrayKlass::initialize(TRAPS) { |
256 void TypeArrayKlass::initialize(TRAPS) { |
257 // Nothing to do. Having this function is handy since objArrayKlasses can be |
257 // Nothing to do. Having this function is handy since objArrayKlasses can be |
258 // initialized by calling initialize on their bottom_klass, see objArrayKlass::initialize |
258 // initialized by calling initialize on their bottom_klass, see ObjArrayKlass::initialize |
259 } |
259 } |
260 |
260 |
261 const char* typeArrayKlass::external_name(BasicType type) { |
261 const char* TypeArrayKlass::external_name(BasicType type) { |
262 switch (type) { |
262 switch (type) { |
263 case T_BOOLEAN: return "[Z"; |
263 case T_BOOLEAN: return "[Z"; |
264 case T_CHAR: return "[C"; |
264 case T_CHAR: return "[C"; |
265 case T_FLOAT: return "[F"; |
265 case T_FLOAT: return "[F"; |
266 case T_DOUBLE: return "[D"; |
266 case T_DOUBLE: return "[D"; |