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