hotspot/src/share/vm/ci/ciInstanceKlass.cpp

Print this page
rev 611 : Merge

@@ -1,10 +1,10 @@
 #ifdef USE_PRAGMA_IDENT_SRC
 #pragma ident "@(#)ciInstanceKlass.cpp  1.45 07/09/28 10:23:23 JVM"
 #endif
 /*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -35,11 +35,13 @@
 
 // ------------------------------------------------------------------
 // ciInstanceKlass::ciInstanceKlass
 //
 // Loaded instance klass.
-ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciKlass(h_k) {
+ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
+  ciKlass(h_k), _non_static_fields(NULL)
+{
   assert(get_Klass()->oop_is_instance(), "wrong type");
   instanceKlass* ik = get_instanceKlass();
 
   AccessFlags access_flags = ik->access_flags();
   _flags = ciFlags(access_flags);

@@ -47,10 +49,11 @@
   _has_subklass = ik->subklass() != NULL;
   _is_initialized = ik->is_initialized();
   // Next line must follow and use the result of the previous line:
   _is_linked = _is_initialized || ik->is_linked();
   _nonstatic_field_size = ik->nonstatic_field_size();
+  _has_nonstatic_fields = ik->has_nonstatic_fields();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
 
   _nof_implementors = ik->nof_implementors();
   for (int i = 0; i < implementors_limit; i++) {
     _implementors[i] = NULL;  // we will fill these lazily

@@ -92,10 +95,11 @@
 {
   assert(name->byte_at(0) != '[', "not an instance klass");
   _is_initialized = false;
   _is_linked = false;
   _nonstatic_field_size = -1;
+  _has_nonstatic_fields = false;
   _nonstatic_fields = NULL;
   _nof_implementors = -1;
   _loader = loader;
   _protection_domain = protection_domain;
   _is_shared = false;

@@ -200,20 +204,21 @@
     tty->print_cr(" ***");
   };
   assert(offset >= 0 && offset < layout_helper(), "offset must be tame");
   #endif
 
-  if (offset < (instanceOopDesc::header_size() * wordSize)) {
+  if (offset < instanceOopDesc::base_offset_in_bytes()) {
     // All header offsets belong properly to java/lang/Object.
     return CURRENT_ENV->Object_klass();
   }
   
   ciInstanceKlass* self = this;
   for (;;) {
     assert(self->is_loaded(), "must be loaded to have size");
     ciInstanceKlass* super = self->super();
-    if (super == NULL || !super->contains_field_offset(offset)) {
+    if (super == NULL || super->nof_nonstatic_fields() == 0 ||
+        !super->contains_field_offset(offset)) {
       return self;
     } else {
       self = super;  // return super->get_canonical_holder(offset)
     }
   }

@@ -336,10 +341,41 @@
   }
   ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
   return field;
 }
 
+// ------------------------------------------------------------------
+// ciInstanceKlass::non_static_fields.
+
+class NonStaticFieldFiller: public FieldClosure {
+  GrowableArray<ciField*>* _arr;
+  ciEnv* _curEnv;
+public:
+  NonStaticFieldFiller(ciEnv* curEnv, GrowableArray<ciField*>* arr) :
+    _curEnv(curEnv), _arr(arr)
+  {}
+  void do_field(fieldDescriptor* fd) {
+    ciField* field = new (_curEnv->arena()) ciField(fd);
+    _arr->append(field);
+  }
+};
+
+GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
+  if (_non_static_fields == NULL) {
+    VM_ENTRY_MARK;
+    ciEnv* curEnv = ciEnv::current();
+    instanceKlass* ik = get_instanceKlass();
+    int max_n_fields = ik->fields()->length()/instanceKlass::next_offset;
+
+    _non_static_fields =
+      new (curEnv->arena()) GrowableArray<ciField*>(max_n_fields);
+    NonStaticFieldFiller filler(curEnv, _non_static_fields);
+    ik->do_nonstatic_fields(&filler);
+  }
+  return _non_static_fields;
+}
+
 static int sort_field_by_offset(ciField** a, ciField** b) {
   return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
   // (no worries about 32-bit overflow...)
 }
 

@@ -349,36 +385,33 @@
   assert(is_loaded(), "must be loaded");
 
   if (_nonstatic_fields != NULL)
     return _nonstatic_fields->length();
 
-  // Size in bytes of my fields, including inherited fields.
-  // About equal to size_helper() - sizeof(oopDesc).
-  int fsize = nonstatic_field_size() * wordSize;
-  if (fsize == 0) {     // easy shortcut
+  if (!has_nonstatic_fields()) {
     Arena* arena = CURRENT_ENV->arena();
     _nonstatic_fields = new (arena) GrowableArray<ciField*>(arena, 0, 0, NULL);
     return 0;
   }
   assert(!is_java_lang_Object(), "bootstrap OK");
 
+  // Size in bytes of my fields, including inherited fields.
+  int fsize = nonstatic_field_size() * heapOopSize;
+
   ciInstanceKlass* super = this->super();
-  int      super_fsize = 0;
-  int      super_flen  = 0;
   GrowableArray<ciField*>* super_fields = NULL;
-  if (super != NULL) {
-    super_fsize  = super->nonstatic_field_size() * wordSize;
-    super_flen   = super->nof_nonstatic_fields();
+  if (super != NULL && super->has_nonstatic_fields()) {
+    int super_fsize  = super->nonstatic_field_size() * heapOopSize;
+    int super_flen   = super->nof_nonstatic_fields();
     super_fields = super->_nonstatic_fields;
     assert(super_flen == 0 || super_fields != NULL, "first get nof_fields");
-  }
-
   // See if I am no larger than my super; if so, I can use his fields.
   if (fsize == super_fsize) {
     _nonstatic_fields = super_fields;
     return super_fields->length();
   }
+  }
 
   GrowableArray<ciField*>* fields = NULL;
   GUARDED_VM_ENTRY({
       fields = compute_nonstatic_fields_impl(super_fields);
     });

@@ -393,24 +426,24 @@
 
   // Now sort them by offset, ascending.
   // (In principle, they could mix with superclass fields.)
   fields->sort(sort_field_by_offset);
 #ifdef ASSERT
-  int last_offset = sizeof(oopDesc);
+  int last_offset = instanceOopDesc::base_offset_in_bytes();
   for (int i = 0; i < fields->length(); i++) {
     ciField* field = fields->at(i);
     int offset = field->offset_in_bytes();
-    int size   = (field->_type == NULL) ? oopSize : field->size_in_bytes();
+    int size   = (field->_type == NULL) ? heapOopSize : field->size_in_bytes();
     assert(last_offset <= offset, "no field overlap");
     if (last_offset > (int)sizeof(oopDesc))
       assert((offset - last_offset) < BytesPerLong, "no big holes");
     // Note:  Two consecutive T_BYTE fields will be separated by wordSize-1
     // padding bytes if one of them is declared by a superclass.
     // This is a minor inefficiency classFileParser.cpp.
     last_offset = offset + size;
   }
-  assert(last_offset <= (int)sizeof(oopDesc) + fsize, "no overflow");
+  assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow");
 #endif
 
   _nonstatic_fields = fields;
   return flen;
 }