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