1 /* 2 * Copyright (c) 1999, 2007, 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/_ciObjArrayKlass.cpp.incl" 27 28 // ciObjArrayKlass 29 // 30 // This class represents a klassOop in the HotSpot virtual machine 31 // whose Klass part is an objArrayKlass. 32 33 // ------------------------------------------------------------------ 34 // ciObjArrayKlass::ciObjArrayKlass 35 // 36 // Constructor for loaded object array klasses. 37 ciObjArrayKlass::ciObjArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) { 38 assert(get_Klass()->oop_is_objArray(), "wrong type"); 39 klassOop element_klassOop = get_objArrayKlass()->bottom_klass(); 40 _base_element_klass = CURRENT_ENV->get_object(element_klassOop)->as_klass(); 41 assert(_base_element_klass->is_instance_klass() || 42 _base_element_klass->is_type_array_klass(), "bad base klass"); 43 if (dimension() == 1) { 44 _element_klass = _base_element_klass; 45 } else { 46 _element_klass = NULL; 47 } 48 if (!ciObjectFactory::is_initialized()) { 49 assert(_element_klass->is_java_lang_Object(), "only arrays of object are shared"); 50 } 51 } 52 53 // ------------------------------------------------------------------ 54 // ciObjArrayKlass::ciObjArrayKlass 55 // 56 // Constructor for unloaded object array klasses. 57 ciObjArrayKlass::ciObjArrayKlass(ciSymbol* array_name, 58 ciKlass* base_element_klass, 59 int dimension) 60 : ciArrayKlass(array_name, 61 dimension, 62 ciObjArrayKlassKlass::make()) { 63 _base_element_klass = base_element_klass; 64 assert(_base_element_klass->is_instance_klass() || 65 _base_element_klass->is_type_array_klass(), "bad base klass"); 66 if (dimension == 1) { 67 _element_klass = base_element_klass; 68 } else { 69 _element_klass = NULL; 70 } 71 } 72 73 // ------------------------------------------------------------------ 74 // ciObjArrayKlass::element_klass 75 // 76 // What is the one-level element type of this array? 77 ciKlass* ciObjArrayKlass::element_klass() { 78 if (_element_klass == NULL) { 79 assert(dimension() > 1, "_element_klass should not be NULL"); 80 // Produce the element klass. 81 if (is_loaded()) { 82 VM_ENTRY_MARK; 83 klassOop element_klassOop = get_objArrayKlass()->element_klass(); 84 _element_klass = CURRENT_THREAD_ENV->get_object(element_klassOop)->as_klass(); 85 } else { 86 VM_ENTRY_MARK; 87 // We are an unloaded array klass. Attempt to fetch our 88 // element klass by name. 89 _element_klass = CURRENT_THREAD_ENV->get_klass_by_name_impl( 90 this, 91 construct_array_name(base_element_klass()->name(), 92 dimension() - 1), 93 false); 94 } 95 } 96 return _element_klass; 97 } 98 99 // ------------------------------------------------------------------ 100 // ciObjArrayKlass::construct_array_name 101 // 102 // Build an array name from an element name and a dimension. 103 ciSymbol* ciObjArrayKlass::construct_array_name(ciSymbol* element_name, 104 int dimension) { 105 EXCEPTION_CONTEXT; 106 int element_len = element_name->utf8_length(); 107 108 symbolOop base_name_sym = element_name->get_symbolOop(); 109 char* name; 110 111 if (base_name_sym->byte_at(0) == '[' || 112 (base_name_sym->byte_at(0) == 'L' && // watch package name 'Lxx' 113 base_name_sym->byte_at(element_len-1) == ';')) { 114 115 int new_len = element_len + dimension + 1; // for the ['s and '\0' 116 name = CURRENT_THREAD_ENV->name_buffer(new_len); 117 118 int pos = 0; 119 for ( ; pos < dimension; pos++) { 120 name[pos] = '['; 121 } 122 strncpy(name+pos, (char*)element_name->base(), element_len); 123 name[new_len-1] = '\0'; 124 } else { 125 int new_len = 3 // for L, ;, and '\0' 126 + dimension // for ['s 127 + element_len; 128 129 name = CURRENT_THREAD_ENV->name_buffer(new_len); 130 int pos = 0; 131 for ( ; pos < dimension; pos++) { 132 name[pos] = '['; 133 } 134 name[pos++] = 'L'; 135 strncpy(name+pos, (char*)element_name->base(), element_len); 136 name[new_len-2] = ';'; 137 name[new_len-1] = '\0'; 138 } 139 return ciSymbol::make(name); 140 } 141 142 // ------------------------------------------------------------------ 143 // ciObjArrayKlass::make_impl 144 // 145 // Implementation of make. 146 ciObjArrayKlass* ciObjArrayKlass::make_impl(ciKlass* element_klass) { 147 148 if (element_klass->is_loaded()) { 149 EXCEPTION_CONTEXT; 150 // The element klass is loaded 151 klassOop array = element_klass->get_Klass()->array_klass(THREAD); 152 if (HAS_PENDING_EXCEPTION) { 153 CLEAR_PENDING_EXCEPTION; 154 CURRENT_THREAD_ENV->record_out_of_memory_failure(); 155 return ciEnv::unloaded_ciobjarrayklass(); 156 } 157 return CURRENT_THREAD_ENV->get_object(array)->as_obj_array_klass(); 158 } 159 160 // The array klass was unable to be made or the element klass was 161 // not loaded. 162 ciSymbol* array_name = construct_array_name(element_klass->name(), 1); 163 if (array_name == ciEnv::unloaded_cisymbol()) { 164 return ciEnv::unloaded_ciobjarrayklass(); 165 } 166 return 167 CURRENT_ENV->get_unloaded_klass(element_klass, array_name) 168 ->as_obj_array_klass(); 169 } 170 171 // ------------------------------------------------------------------ 172 // ciObjArrayKlass::make 173 // 174 // Make an array klass corresponding to the specified primitive type. 175 ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass) { 176 assert(element_klass->is_java_klass(), "wrong kind of klass"); 177 GUARDED_VM_ENTRY(return make_impl(element_klass);) 178 }