1 /* 2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 # include "incls/_precompiled.incl" 26 # include "incls/_typeArrayKlass.cpp.incl" 27 28 bool typeArrayKlass::compute_is_subtype_of(klassOop k) { 29 if (!k->klass_part()->oop_is_typeArray()) { 30 return arrayKlass::compute_is_subtype_of(k); 31 } 32 33 typeArrayKlass* tak = typeArrayKlass::cast(k); 34 if (dimension() != tak->dimension()) return false; 35 36 return element_type() == tak->element_type(); 37 } 38 39 klassOop typeArrayKlass::create_klass(BasicType type, int scale, 40 const char* name_str, TRAPS) { 41 typeArrayKlass o; 42 43 symbolHandle sym(symbolOop(NULL)); 44 // bootstrapping: don't create sym if symbolKlass not created yet 45 if (Universe::symbolKlassObj() != NULL && name_str != NULL) { 46 sym = oopFactory::new_symbol_handle(name_str, CHECK_NULL); 47 } 48 KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj()); 49 50 arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL); 51 typeArrayKlass* ak = typeArrayKlass::cast(k()); 52 ak->set_name(sym()); 53 ak->set_layout_helper(array_layout_helper(type)); 54 assert(scale == (1 << ak->log2_element_size()), "scale must check out"); 55 assert(ak->oop_is_javaArray(), "sanity"); 56 assert(ak->oop_is_typeArray(), "sanity"); 57 ak->set_max_length(arrayOopDesc::max_array_length(type)); 58 assert(k()->size() > header_size(), "bad size"); 59 60 // Call complete_create_array_klass after all instance variables have been initialized. 61 KlassHandle super (THREAD, k->super()); 62 complete_create_array_klass(k, super, CHECK_NULL); 63 64 return k(); 65 } 66 67 typeArrayOop typeArrayKlass::allocate(int length, TRAPS) { 68 assert(log2_element_size() >= 0, "bad scale"); 69 if (length >= 0) { 70 if (length <= max_length()) { 71 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); 72 KlassHandle h_k(THREAD, as_klassOop()); 73 typeArrayOop t; 74 CollectedHeap* ch = Universe::heap(); 75 if (size < ch->large_typearray_limit()) { 76 t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); 77 } else { 78 t = (typeArrayOop)CollectedHeap::large_typearray_allocate(h_k, (int)size, length, CHECK_NULL); 79 } 80 assert(t->is_parsable(), "Don't publish unless parsable"); 81 return t; 82 } else { 83 report_java_out_of_memory("Requested array size exceeds VM limit"); 84 THROW_OOP_0(Universe::out_of_memory_error_array_size()); 85 } 86 } else { 87 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); 88 } 89 } 90 91 typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) { 92 if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); 93 int size = typeArrayOopDesc::object_size(layout_helper(), length); 94 KlassHandle h_k(THREAD, as_klassOop()); 95 typeArrayOop t = (typeArrayOop) 96 CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL); 97 assert(t->is_parsable(), "Can't publish until parsable"); 98 return t; 99 } 100 101 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { 102 // For typeArrays this is only called for the last dimension 103 assert(rank == 1, "just checking"); 104 int length = *last_size; 105 return allocate(length, THREAD); 106 } 107 108 109 void typeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) { 110 assert(s->is_typeArray(), "must be type array"); 111 112 // Check destination 113 if (!d->is_typeArray() || element_type() != typeArrayKlass::cast(d->klass())->element_type()) { 114 THROW(vmSymbols::java_lang_ArrayStoreException()); 115 } 116 117 // Check is all offsets and lengths are non negative 118 if (src_pos < 0 || dst_pos < 0 || length < 0) { 119 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); 120 } 121 // Check if the ranges are valid 122 if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length()) 123 || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) { 124 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); 125 } 126 // Check zero copy 127 if (length == 0) 128 return; 129 130 // This is an attempt to make the copy_array fast. 131 int l2es = log2_element_size(); 132 int ihs = array_header_in_bytes() / wordSize; 133 char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es); 134 char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es); 135 Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); 136 } 137 138 139 // create a klass of array holding typeArrays 140 klassOop typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { 141 typeArrayKlassHandle h_this(THREAD, as_klassOop()); 142 return array_klass_impl(h_this, or_null, n, THREAD); 143 } 144 145 klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_null, int n, TRAPS) { 146 int dimension = h_this->dimension(); 147 assert(dimension <= n, "check order of chain"); 148 if (dimension == n) 149 return h_this(); 150 151 objArrayKlassHandle h_ak(THREAD, h_this->higher_dimension()); 152 if (h_ak.is_null()) { 153 if (or_null) return NULL; 154 155 ResourceMark rm; 156 JavaThread *jt = (JavaThread *)THREAD; 157 { 158 MutexLocker mc(Compile_lock, THREAD); // for vtables 159 // Atomic create higher dimension and link into list 160 MutexLocker mu(MultiArray_lock, THREAD); 161 162 h_ak = objArrayKlassHandle(THREAD, h_this->higher_dimension()); 163 if (h_ak.is_null()) { 164 klassOop oak = objArrayKlassKlass::cast( 165 Universe::objArrayKlassKlassObj())->allocate_objArray_klass( 166 dimension + 1, h_this, CHECK_NULL); 167 h_ak = objArrayKlassHandle(THREAD, oak); 168 h_ak->set_lower_dimension(h_this()); 169 h_this->set_higher_dimension(h_ak()); 170 assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); 171 } 172 } 173 } else { 174 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); 175 } 176 if (or_null) { 177 return h_ak->array_klass_or_null(n); 178 } 179 return h_ak->array_klass(n, CHECK_NULL); 180 } 181 182 klassOop typeArrayKlass::array_klass_impl(bool or_null, TRAPS) { 183 return array_klass_impl(or_null, dimension() + 1, THREAD); 184 } 185 186 int typeArrayKlass::oop_size(oop obj) const { 187 assert(obj->is_typeArray(),"must be a type array"); 188 typeArrayOop t = typeArrayOop(obj); 189 return t->object_size(); 190 } 191 192 void typeArrayKlass::oop_follow_contents(oop obj) { 193 assert(obj->is_typeArray(),"must be a type array"); 194 // Performance tweak: We skip iterating over the klass pointer since we 195 // know that Universe::typeArrayKlass never moves. 196 } 197 198 #ifndef SERIALGC 199 void typeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { 200 assert(obj->is_typeArray(),"must be a type array"); 201 // Performance tweak: We skip iterating over the klass pointer since we 202 // know that Universe::typeArrayKlass never moves. 203 } 204 #endif // SERIALGC 205 206 int typeArrayKlass::oop_adjust_pointers(oop obj) { 207 assert(obj->is_typeArray(),"must be a type array"); 208 typeArrayOop t = typeArrayOop(obj); 209 // Performance tweak: We skip iterating over the klass pointer since we 210 // know that Universe::typeArrayKlass never moves. 211 return t->object_size(); 212 } 213 214 int typeArrayKlass::oop_oop_iterate(oop obj, OopClosure* blk) { 215 assert(obj->is_typeArray(),"must be a type array"); 216 typeArrayOop t = typeArrayOop(obj); 217 // Performance tweak: We skip iterating over the klass pointer since we 218 // know that Universe::typeArrayKlass never moves. 219 return t->object_size(); 220 } 221 222 int typeArrayKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) { 223 assert(obj->is_typeArray(),"must be a type array"); 224 typeArrayOop t = typeArrayOop(obj); 225 // Performance tweak: We skip iterating over the klass pointer since we 226 // know that Universe::typeArrayKlass never moves. 227 return t->object_size(); 228 } 229 230 #ifndef SERIALGC 231 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { 232 assert(obj->is_typeArray(),"must be a type array"); 233 } 234 235 int 236 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 237 assert(obj->is_typeArray(),"must be a type array"); 238 return typeArrayOop(obj)->object_size(); 239 } 240 241 int 242 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, 243 HeapWord* beg_addr, HeapWord* end_addr) { 244 assert(obj->is_typeArray(),"must be a type array"); 245 return typeArrayOop(obj)->object_size(); 246 } 247 #endif // SERIALGC 248 249 void typeArrayKlass::initialize(TRAPS) { 250 // Nothing to do. Having this function is handy since objArrayKlasses can be 251 // initialized by calling initialize on their bottom_klass, see objArrayKlass::initialize 252 } 253 254 const char* typeArrayKlass::external_name(BasicType type) { 255 switch (type) { 256 case T_BOOLEAN: return "[Z"; 257 case T_CHAR: return "[C"; 258 case T_FLOAT: return "[F"; 259 case T_DOUBLE: return "[D"; 260 case T_BYTE: return "[B"; 261 case T_SHORT: return "[S"; 262 case T_INT: return "[I"; 263 case T_LONG: return "[J"; 264 default: ShouldNotReachHere(); 265 } 266 return NULL; 267 } 268 269 #ifndef PRODUCT 270 // Printing 271 272 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) { 273 for (int index = 0; index < print_len; index++) { 274 st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true"); 275 } 276 } 277 278 279 static void print_char_array(typeArrayOop ta, int print_len, outputStream* st) { 280 for (int index = 0; index < print_len; index++) { 281 jchar c = ta->char_at(index); 282 st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' '); 283 } 284 } 285 286 287 static void print_float_array(typeArrayOop ta, int print_len, outputStream* st) { 288 for (int index = 0; index < print_len; index++) { 289 st->print_cr(" - %3d: %g", index, ta->float_at(index)); 290 } 291 } 292 293 294 static void print_double_array(typeArrayOop ta, int print_len, outputStream* st) { 295 for (int index = 0; index < print_len; index++) { 296 st->print_cr(" - %3d: %g", index, ta->double_at(index)); 297 } 298 } 299 300 301 static void print_byte_array(typeArrayOop ta, int print_len, outputStream* st) { 302 for (int index = 0; index < print_len; index++) { 303 jbyte c = ta->byte_at(index); 304 st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' '); 305 } 306 } 307 308 309 static void print_short_array(typeArrayOop ta, int print_len, outputStream* st) { 310 for (int index = 0; index < print_len; index++) { 311 int v = ta->ushort_at(index); 312 st->print_cr(" - %3d: 0x%x\t %d", index, v, v); 313 } 314 } 315 316 317 static void print_int_array(typeArrayOop ta, int print_len, outputStream* st) { 318 for (int index = 0; index < print_len; index++) { 319 jint v = ta->int_at(index); 320 st->print_cr(" - %3d: 0x%x %d", index, v, v); 321 } 322 } 323 324 325 static void print_long_array(typeArrayOop ta, int print_len, outputStream* st) { 326 for (int index = 0; index < print_len; index++) { 327 jlong v = ta->long_at(index); 328 st->print_cr(" - %3d: 0x%x 0x%x", index, high(v), low(v)); 329 } 330 } 331 332 333 void typeArrayKlass::oop_print_on(oop obj, outputStream* st) { 334 arrayKlass::oop_print_on(obj, st); 335 typeArrayOop ta = typeArrayOop(obj); 336 int print_len = MIN2((intx) ta->length(), MaxElementPrintSize); 337 switch (element_type()) { 338 case T_BOOLEAN: print_boolean_array(ta, print_len, st); break; 339 case T_CHAR: print_char_array(ta, print_len, st); break; 340 case T_FLOAT: print_float_array(ta, print_len, st); break; 341 case T_DOUBLE: print_double_array(ta, print_len, st); break; 342 case T_BYTE: print_byte_array(ta, print_len, st); break; 343 case T_SHORT: print_short_array(ta, print_len, st); break; 344 case T_INT: print_int_array(ta, print_len, st); break; 345 case T_LONG: print_long_array(ta, print_len, st); break; 346 default: ShouldNotReachHere(); 347 } 348 int remaining = ta->length() - print_len; 349 if (remaining > 0) { 350 tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); 351 } 352 } 353 354 #endif // PRODUCT 355 356 const char* typeArrayKlass::internal_name() const { 357 return Klass::external_name(); 358 }