< prev index next >

src/share/vm/oops/objArrayKlass.cpp

Print this page




  29 #include "classfile/systemDictionary.hpp"
  30 #include "classfile/vmSymbols.hpp"
  31 #include "gc/shared/collectedHeap.inline.hpp"
  32 #include "gc/shared/specialized_oop_closures.hpp"
  33 #include "memory/iterator.inline.hpp"
  34 #include "memory/metadataFactory.hpp"
  35 #include "memory/resourceArea.hpp"
  36 #include "memory/universe.inline.hpp"
  37 #include "oops/arrayKlass.inline.hpp"
  38 #include "oops/instanceKlass.hpp"
  39 #include "oops/klass.inline.hpp"
  40 #include "oops/objArrayKlass.inline.hpp"
  41 #include "oops/objArrayOop.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "oops/symbol.hpp"
  44 #include "runtime/handles.inline.hpp"
  45 #include "runtime/mutexLocker.hpp"
  46 #include "utilities/copy.hpp"
  47 #include "utilities/macros.hpp"
  48 
  49 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) {
  50   assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
  51       "array klasses must be same size as InstanceKlass");
  52 
  53   int size = ArrayKlass::static_size(ObjArrayKlass::header_size());
  54 
  55   return new (loader_data, size, THREAD) ObjArrayKlass(n, klass_handle, name);
  56 }
  57 
  58 Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
  59                                                 int n, KlassHandle element_klass, TRAPS) {
  60 
  61   // Eagerly allocate the direct array supertype.
  62   KlassHandle super_klass = KlassHandle();
  63   if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) {
  64     KlassHandle element_super (THREAD, element_klass->super());
  65     if (element_super.not_null()) {
  66       // The element type has a direct super.  E.g., String[] has direct super of Object[].
  67       super_klass = KlassHandle(THREAD, element_super->array_klass_or_null());
  68       bool supers_exist = super_klass.not_null();
  69       // Also, see if the element has secondary supertypes.
  70       // We need an array type for each.
  71       Array<Klass*>* element_supers = element_klass->secondary_supers();
  72       for( int i = element_supers->length()-1; i >= 0; i-- ) {
  73         Klass* elem_super = element_supers->at(i);
  74         if (elem_super->array_klass_or_null() == NULL) {
  75           supers_exist = false;
  76           break;
  77         }
  78       }
  79       if (!supers_exist) {
  80         // Oops.  Not allocated yet.  Back out, allocate it, and retry.
  81         KlassHandle ek;
  82         {
  83           MutexUnlocker mu(MultiArray_lock);
  84           MutexUnlocker mc(Compile_lock);   // for vtables
  85           Klass* sk = element_super->array_klass(CHECK_0);
  86           super_klass = KlassHandle(THREAD, sk);
  87           for( int i = element_supers->length()-1; i >= 0; i-- ) {
  88             KlassHandle elem_super (THREAD, element_supers->at(i));
  89             elem_super->array_klass(CHECK_0);
  90           }
  91           // Now retry from the beginning
  92           Klass* klass_oop = element_klass->array_klass(n, CHECK_0);
  93           // Create a handle because the enclosing brace, when locking
  94           // can cause a gc.  Better to have this function return a Handle.
  95           ek = KlassHandle(THREAD, klass_oop);
  96         }  // re-lock
  97         return ek();
  98       }
  99     } else {
 100       // The element type is already Object.  Object[] has direct super of Object.
 101       super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass());
 102     }
 103   }
 104 
 105   // Create type name for klass.
 106   Symbol* name = NULL;
 107   if (!element_klass->is_instance_klass() ||
 108       (name = InstanceKlass::cast(element_klass())->array_name()) == NULL) {
 109 
 110     ResourceMark rm(THREAD);
 111     char *name_str = element_klass->name()->as_C_string();
 112     int len = element_klass->name()->utf8_length();
 113     char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
 114     int idx = 0;
 115     new_str[idx++] = '[';
 116     if (element_klass->is_instance_klass()) { // it could be an array or simple type
 117       new_str[idx++] = 'L';
 118     }
 119     memcpy(&new_str[idx], name_str, len * sizeof(char));
 120     idx += len;
 121     if (element_klass->is_instance_klass()) {
 122       new_str[idx++] = ';';
 123     }
 124     new_str[idx++] = '\0';
 125     name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
 126     if (element_klass->is_instance_klass()) {
 127       InstanceKlass* ik = InstanceKlass::cast(element_klass());
 128       ik->set_array_name(name);
 129     }
 130   }
 131 
 132   // Initialize instance variables
 133   ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_0);
 134 
 135   // Add all classes to our internal class loader list here,
 136   // including classes in the bootstrap (NULL) class loader.
 137   // GC walks these as strong roots.
 138   loader_data->add_class(oak);
 139 
 140   ModuleEntry* module = oak->module();
 141   assert(module != NULL, "No module entry for array");
 142 
 143   // Call complete_create_array_klass after all instance variables has been initialized.
 144   ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 145 
 146   return oak;
 147 }
 148 
 149 ObjArrayKlass::ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name) : ArrayKlass(name) {
 150   this->set_dimension(n);
 151   this->set_element_klass(element_klass());
 152   // decrement refcount because object arrays are not explicitly freed.  The
 153   // InstanceKlass array_name() keeps the name counted while the klass is
 154   // loaded.
 155   name->decrement_refcount();
 156 
 157   Klass* bk;
 158   if (element_klass->is_objArray_klass()) {
 159     bk = ObjArrayKlass::cast(element_klass())->bottom_klass();
 160   } else {
 161     bk = element_klass();
 162   }
 163   assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
 164   this->set_bottom_klass(bk);
 165   this->set_class_loader_data(bk->class_loader_data());
 166 
 167   this->set_layout_helper(array_layout_helper(T_OBJECT));
 168   assert(this->is_array_klass(), "sanity");
 169   assert(this->is_objArray_klass(), "sanity");
 170 }
 171 
 172 int ObjArrayKlass::oop_size(oop obj) const {
 173   assert(obj->is_objArray(), "must be object array");
 174   return objArrayOop(obj)->object_size();
 175 }
 176 
 177 objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
 178   if (length >= 0) {
 179     if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
 180       int size = objArrayOopDesc::object_size(length);
 181       KlassHandle h_k(THREAD, this);
 182       return (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, THREAD);
 183     } else {
 184       report_java_out_of_memory("Requested array size exceeds VM limit");
 185       JvmtiExport::post_array_size_exhausted();
 186       THROW_OOP_0(Universe::out_of_memory_error_array_size());
 187     }
 188   } else {
 189     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
 190   }
 191 }
 192 
 193 static int multi_alloc_counter = 0;
 194 
 195 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
 196   int length = *sizes;
 197   // Call to lower_dimension uses this pointer, so most be called before a
 198   // possible GC
 199   KlassHandle h_lower_dimension(THREAD, lower_dimension());
 200   // If length < 0 allocate will throw an exception.
 201   objArrayOop array = allocate(length, CHECK_NULL);
 202   objArrayHandle h_array (THREAD, array);
 203   if (rank > 1) {
 204     if (length != 0) {
 205       for (int index = 0; index < length; index++) {
 206         ArrayKlass* ak = ArrayKlass::cast(h_lower_dimension());
 207         oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
 208         h_array->obj_at_put(index, sub_array);
 209       }
 210     } else {
 211       // Since this array dimension has zero length, nothing will be
 212       // allocated, however the lower dimension values must be checked
 213       // for illegal values.
 214       for (int i = 0; i < rank - 1; ++i) {
 215         sizes += 1;
 216         if (*sizes < 0) {
 217           THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
 218         }
 219       }
 220     }
 221   }
 222   return h_array();
 223 }
 224 
 225 // Either oop or narrowOop depending on UseCompressedOops.
 226 template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src,




  29 #include "classfile/systemDictionary.hpp"
  30 #include "classfile/vmSymbols.hpp"
  31 #include "gc/shared/collectedHeap.inline.hpp"
  32 #include "gc/shared/specialized_oop_closures.hpp"
  33 #include "memory/iterator.inline.hpp"
  34 #include "memory/metadataFactory.hpp"
  35 #include "memory/resourceArea.hpp"
  36 #include "memory/universe.inline.hpp"
  37 #include "oops/arrayKlass.inline.hpp"
  38 #include "oops/instanceKlass.hpp"
  39 #include "oops/klass.inline.hpp"
  40 #include "oops/objArrayKlass.inline.hpp"
  41 #include "oops/objArrayOop.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "oops/symbol.hpp"
  44 #include "runtime/handles.inline.hpp"
  45 #include "runtime/mutexLocker.hpp"
  46 #include "utilities/copy.hpp"
  47 #include "utilities/macros.hpp"
  48 
  49 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
  50   assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
  51       "array klasses must be same size as InstanceKlass");
  52 
  53   int size = ArrayKlass::static_size(ObjArrayKlass::header_size());
  54 
  55   return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name);
  56 }
  57 
  58 Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
  59                                                 int n, Klass* element_klass, TRAPS) {
  60 
  61   // Eagerly allocate the direct array supertype.
  62   Klass* super_klass = NULL;
  63   if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) {
  64     Klass* element_super = element_klass->super();
  65     if (element_super != NULL) {
  66       // The element type has a direct super.  E.g., String[] has direct super of Object[].
  67       super_klass = element_super->array_klass_or_null();
  68       bool supers_exist = super_klass != NULL;
  69       // Also, see if the element has secondary supertypes.
  70       // We need an array type for each.
  71       Array<Klass*>* element_supers = element_klass->secondary_supers();
  72       for( int i = element_supers->length()-1; i >= 0; i-- ) {
  73         Klass* elem_super = element_supers->at(i);
  74         if (elem_super->array_klass_or_null() == NULL) {
  75           supers_exist = false;
  76           break;
  77         }
  78       }
  79       if (!supers_exist) {
  80         // Oops.  Not allocated yet.  Back out, allocate it, and retry.
  81         Klass* ek = NULL;
  82         {
  83           MutexUnlocker mu(MultiArray_lock);
  84           MutexUnlocker mc(Compile_lock);   // for vtables
  85           super_klass = element_super->array_klass(CHECK_0);

  86           for( int i = element_supers->length()-1; i >= 0; i-- ) {
  87             Klass* elem_super = element_supers->at(i);
  88             elem_super->array_klass(CHECK_0);
  89           }
  90           // Now retry from the beginning
  91           ek = element_klass->array_klass(n, CHECK_0);



  92         }  // re-lock
  93         return ek;
  94       }
  95     } else {
  96       // The element type is already Object.  Object[] has direct super of Object.
  97       super_klass = SystemDictionary::Object_klass();
  98     }
  99   }
 100 
 101   // Create type name for klass.
 102   Symbol* name = NULL;
 103   if (!element_klass->is_instance_klass() ||
 104       (name = InstanceKlass::cast(element_klass)->array_name()) == NULL) {
 105 
 106     ResourceMark rm(THREAD);
 107     char *name_str = element_klass->name()->as_C_string();
 108     int len = element_klass->name()->utf8_length();
 109     char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
 110     int idx = 0;
 111     new_str[idx++] = '[';
 112     if (element_klass->is_instance_klass()) { // it could be an array or simple type
 113       new_str[idx++] = 'L';
 114     }
 115     memcpy(&new_str[idx], name_str, len * sizeof(char));
 116     idx += len;
 117     if (element_klass->is_instance_klass()) {
 118       new_str[idx++] = ';';
 119     }
 120     new_str[idx++] = '\0';
 121     name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
 122     if (element_klass->is_instance_klass()) {
 123       InstanceKlass* ik = InstanceKlass::cast(element_klass);
 124       ik->set_array_name(name);
 125     }
 126   }
 127 
 128   // Initialize instance variables
 129   ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_0);
 130 
 131   // Add all classes to our internal class loader list here,
 132   // including classes in the bootstrap (NULL) class loader.
 133   // GC walks these as strong roots.
 134   loader_data->add_class(oak);
 135 
 136   ModuleEntry* module = oak->module();
 137   assert(module != NULL, "No module entry for array");
 138 
 139   // Call complete_create_array_klass after all instance variables has been initialized.
 140   ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 141 
 142   return oak;
 143 }
 144 
 145 ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name) {
 146   this->set_dimension(n);
 147   this->set_element_klass(element_klass);
 148   // decrement refcount because object arrays are not explicitly freed.  The
 149   // InstanceKlass array_name() keeps the name counted while the klass is
 150   // loaded.
 151   name->decrement_refcount();
 152 
 153   Klass* bk;
 154   if (element_klass->is_objArray_klass()) {
 155     bk = ObjArrayKlass::cast(element_klass)->bottom_klass();
 156   } else {
 157     bk = element_klass;
 158   }
 159   assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
 160   this->set_bottom_klass(bk);
 161   this->set_class_loader_data(bk->class_loader_data());
 162 
 163   this->set_layout_helper(array_layout_helper(T_OBJECT));
 164   assert(this->is_array_klass(), "sanity");
 165   assert(this->is_objArray_klass(), "sanity");
 166 }
 167 
 168 int ObjArrayKlass::oop_size(oop obj) const {
 169   assert(obj->is_objArray(), "must be object array");
 170   return objArrayOop(obj)->object_size();
 171 }
 172 
 173 objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
 174   if (length >= 0) {
 175     if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
 176       int size = objArrayOopDesc::object_size(length);
 177       return (objArrayOop)CollectedHeap::array_allocate(this, size, length, THREAD);

 178     } else {
 179       report_java_out_of_memory("Requested array size exceeds VM limit");
 180       JvmtiExport::post_array_size_exhausted();
 181       THROW_OOP_0(Universe::out_of_memory_error_array_size());
 182     }
 183   } else {
 184     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
 185   }
 186 }
 187 
 188 static int multi_alloc_counter = 0;
 189 
 190 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
 191   int length = *sizes;
 192   // Call to lower_dimension uses this pointer, so most be called before a
 193   // possible GC
 194   Klass* ld_klass = lower_dimension();
 195   // If length < 0 allocate will throw an exception.
 196   objArrayOop array = allocate(length, CHECK_NULL);
 197   objArrayHandle h_array (THREAD, array);
 198   if (rank > 1) {
 199     if (length != 0) {
 200       for (int index = 0; index < length; index++) {
 201         ArrayKlass* ak = ArrayKlass::cast(ld_klass);
 202         oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
 203         h_array->obj_at_put(index, sub_array);
 204       }
 205     } else {
 206       // Since this array dimension has zero length, nothing will be
 207       // allocated, however the lower dimension values must be checked
 208       // for illegal values.
 209       for (int i = 0; i < rank - 1; ++i) {
 210         sizes += 1;
 211         if (*sizes < 0) {
 212           THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
 213         }
 214       }
 215     }
 216   }
 217   return h_array();
 218 }
 219 
 220 // Either oop or narrowOop depending on UseCompressedOops.
 221 template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src,


< prev index next >